Comparing version 0.0.0 to 0.0.1
@@ -56,3 +56,3 @@ /* Copyright (c) 2012 Rod Vagg <@rvagg> */ | ||
this.db = db | ||
callback() | ||
callback(null, this.pub) | ||
this.pub.emit('ready') | ||
@@ -69,2 +69,3 @@ } | ||
//TODO: we can crash Node by submitting an operation between close() and the actual closing of the database | ||
, close: function (callback) { | ||
@@ -208,7 +209,9 @@ if (this.isOpen()) { | ||
, readStream: function (options) { | ||
if (typeof options != 'object') | ||
options = {} | ||
return readStream.create( | ||
options || {} | ||
options | ||
, this | ||
, function () { | ||
return bridge.createIterator(this.db) | ||
return bridge.createIterator(this.db, options) | ||
}.bind(this) | ||
@@ -238,12 +241,18 @@ ) | ||
, createDatabase = function (location, options) { | ||
, createDatabase = function (location, options, callback) { | ||
if (typeof options == 'function') { | ||
callback = options | ||
options = {} | ||
} | ||
if (typeof callback != 'function') | ||
throw new errors.InitializationError('Must provide a callback function') | ||
if (typeof location != 'string') | ||
throw new errors.InitializationError('Must provide a location for the database') | ||
return callback(new errors.InitializationError('Must provide a location for the database')) | ||
return databaseCreator.create(location, options) | ||
var db = databaseCreator.create(location, options) | ||
db.open(callback) | ||
} | ||
module.exports = { | ||
createDatabase : createDatabase | ||
, copy : require('./util').copy | ||
} | ||
module.exports = createDatabase | ||
module.exports.copy = require('./util').copy |
/* Copyright (c) 2012 Rod Vagg <@rvagg> */ | ||
var Stream = require("stream").Stream | ||
, inherits = require("inherits") | ||
, BufferStream = require('bufferstream') | ||
, toEncoding = require('./util').toEncoding | ||
, toBuffer = require('./util').toBuffer | ||
, Creator = require('./creator').Creator | ||
@@ -20,2 +20,7 @@ | ||
if (this._options.start) | ||
this._options.start = toBuffer(this._options.start) | ||
if (this._options.end) | ||
this._options.end = toBuffer(this._options.end) | ||
var ready = function () { | ||
@@ -22,0 +27,0 @@ if (this._status == 'ended') |
/* Copyright (c) 2012 Rod Vagg <@rvagg> */ | ||
var toBuffer = function (data, encoding) { | ||
return data === undefined || data === null || Buffer.isBuffer(data) ? data : new Buffer('' + data, encoding) | ||
if (encoding == 'json') { | ||
data = JSON.stringify(data) | ||
encoding = 'utf8' | ||
} | ||
return data === undefined || data === null || Buffer.isBuffer(data) ? data : new Buffer(String(data), encoding) | ||
} | ||
, toEncoding = function (buffer, encoding) { | ||
return encoding == 'binary' ? buffer : buffer.toString(encoding) | ||
return encoding == 'binary' | ||
? buffer | ||
: encoding == 'json' | ||
? JSON.parse(buffer.toString('utf8')) | ||
: buffer.toString(encoding) | ||
} | ||
@@ -10,0 +18,0 @@ |
/* Copyright (c) 2012 Rod Vagg <@rvagg> */ | ||
var Stream = require("stream").Stream | ||
, inherits = require("inherits") | ||
, concatStream = require('concat-stream') | ||
@@ -6,0 +5,0 @@ |
{ | ||
"name" : "levelup" | ||
, "version" : "0.0.0" | ||
, "keywords" : [ "leveldb", "levelup", "stream", "database", "db", "store", "storage", "json" ] | ||
, "version" : "0.0.1" | ||
, "main" : "lib/levelup.js" | ||
, "dependencies" : { | ||
"errno" : ">=0.0.2" | ||
"errno" : "~0.0.2" | ||
, "bindings" : "~1.0.0" | ||
, "concat-stream" : ">=0.0.8" | ||
, "concat-stream" : "~0.0.8" | ||
, "bufferstream" : "~0.5.1" | ||
} | ||
@@ -10,0 +12,0 @@ , "devDependencies" : { |
LevelUP | ||
======= | ||
Fast & simple storage; a Node.js-style LevelDB wrapper | ||
------------------------------------------------------ | ||
Fast & simple storage - a Node.js-style LevelDB wrapper | ||
------------------------------------------------------- | ||
@@ -20,23 +20,21 @@ **[LevelDB](http://code.google.com/p/leveldb/)** is a simple key/value data store built by Google, inspired by BigTable. It's used in Google Chrome and many other products. LevelDB supports arbitrary byte arrays as both keys and values, singular *get*, *put* and *delete* operations, *batched put and delete*, forward and reverse iteration and simple compression using the [Snappy](http://code.google.com/p/snappy/) algorithm which is optimised for speed over compression. | ||
// 1) create our database object, supply location and options | ||
var db = levelup.createDatabase('./mydb', { createIfMissing: true , errorIfExists: false }) | ||
// 1) Create our database, supply location and options. | ||
// This will create or open the underlying LevelDB store. | ||
var options = { createIfMissing: true, errorIfExists: false } | ||
levelup('./mydb', options, function (err, db) { | ||
if (err) return console.log('Ooops!', err) | ||
// 2) open the database, this will create or open the underlying LevelDB store | ||
db.open(function (err) { | ||
// 3) put a key & value | ||
// 2) put a key & value | ||
db.put('name', 'LevelUP', function (err) { | ||
if (err) throw err | ||
if (err) return console.log('Ooops!', err) // some kind of I/O error | ||
// 4) fetch by key | ||
// 3) fetch by key | ||
db.get('name', function (err, value) { | ||
if (err) throw err // likely the key was not found | ||
if (err) return console.log('Ooops!', err) // likely the key was not found | ||
// ta da! | ||
console.log('name=' + value) | ||
}) | ||
}) | ||
}) | ||
``` | ||
@@ -46,3 +44,3 @@ | ||
`createDatabase()` takes an optional options object as its second argument; the following properties are accepted: | ||
`levelup()` takes an optional options object as its second argument; the following properties are accepted: | ||
@@ -53,6 +51,6 @@ * `createIfMissing` *(boolean)*: If `true`, will initialise an empty database at the specified location if one doesn't already exit. If `false` and a database doesn't exist you will receive an error in your `open()` callback and your database won't open. Defaults to `false`. | ||
* `encoding` *(string)*: The encoding of the keys and values passed through Node.js' `Buffer` implementation (see `[Buffer#toString()](http://nodejs.org/docs/latest/api/buffer.html#buffer_buf_tostring_encoding_start_end)`) | ||
<p>`'utf8'` is the default encoding for both keys and values so you can simply pass in strings and expect strings from your `get()` operations. You can also pass `Buffer` objects as keys and/or values and converstion will be performed.</p> | ||
* `encoding` *(string)*: The encoding of the keys and values passed through Node.js' `Buffer` implementation (see [Buffer#toString()](http://nodejs.org/docs/latest/api/buffer.html#buffer_buf_tostring_encoding_start_end)) | ||
<p><code>'utf8'</code> is the default encoding for both keys and values so you can simply pass in strings and expect strings from your <code>get()</code> operations. You can also pass <code>Buffer</code> objects as keys and/or values and converstion will be performed.</p> | ||
<p>Supported encodings are: hex, utf8, ascii, binary, base64, ucs2, utf16le.</p> | ||
<p>**json** encoding will be supported in a future release, likely stored as utf8 strings.</p> | ||
<p><code>'json'</code> encoding is also supported, see below.</p> | ||
@@ -77,3 +75,3 @@ * `keyEncoding` and `valueEncoding` *(string)*: use instead of `encoding` to specify the exact encoding of both the keys and the values in this database. | ||
db.batch(ops, function (err) { | ||
if (err) throw err | ||
if (err) return console.log('Ooops!', err) | ||
console.log('Great success dear leader!') | ||
@@ -108,5 +106,11 @@ }) | ||
Additionally, you can supply an options object as the first parameter to `readStream()` with the following options: | ||
* `'start'`: the key you wish to start the read at. By default it will start at the beginning of the store. Note that the *start* doesn't have to be an actual key that exists, LevelDB will simply find the *next* key, greater than the key you provide. | ||
* `'end'`: the key you wish to end the read on. By default it will continue until the end of the store. Again, the *end* doesn't have to be an actual key as a `<`-type operation is performed to detect the end. You can also use the `destroy()` method instead of supplying an `'end'` parameter to achieve the same effect. | ||
### WriteStream | ||
A **WriteStream** can be obtained by calling the `writeStream()` method. The resulting stream is a complete Node.js-style [Writable Stream](http://nodejs.org/docs/latest/api/stream.html#stream_writable_stream) which accepts objects with `'key'` and `'value'` pairs on its `write()` method. The WriteStream will buffer writes and submit them as a `batch()` operation where the writes occur on the same event loop tick, otherwise they are treated as simple `put()` operations. | ||
A **WriteStream** can be obtained by calling the `writeStream()` method. The resulting stream is a complete Node.js-style [Writable Stream](http://nodejs.org/docs/latest/api/stream.html#stream_writable_stream) which accepts objects with `'key'` and `'value'` pairs on its `write()` method. Tce WriteStream will buffer writes and submit them as a `batch()` operation where the writes occur on the same event loop tick, otherwise they are treated as simple `put()` operations. | ||
@@ -142,6 +146,11 @@ ```js | ||
JSON | ||
---- | ||
You specify `'json'` encoding for both keys and/or values, you can then supply JavaScript objects to LevelUP and receive them from all fetch operations, including ReadStreams. LevelUP will automatically *stringify* your objects and store them as *utf8* and parse the strings back into objects before passing them back to you. | ||
Important considerations | ||
------------------------ | ||
* LevelDB is thread-safe but is suitable for accessing with multiple processes. You should only ever have a LevelDB database open from a single Node.js process. | ||
* LevelDB is thread-safe but is **not** suitable for accessing with multiple processes. You should only ever have a LevelDB database open from a single Node.js process. | ||
@@ -151,6 +160,3 @@ TODO | ||
* JSON encoding/decoding | ||
* ReadStream reverse read | ||
* ReadStream optional 'start' key | ||
* ReadStream optional 'end' key | ||
* Filter streams, e.g.: KeyReadStream, ValueReadStream | ||
@@ -160,3 +166,3 @@ * *Windows support, maybe* | ||
Licence & Copyright | ||
Licence & copyright | ||
------------------- | ||
@@ -163,0 +169,0 @@ |
/* Copyright (c) 2012 Rod Vagg <@rvagg> */ | ||
/*global commonSetUp:true, commonTearDown:true, loadBinaryTestData:true, binaryTestDataMD5Sum:true, checkBinaryTestData:true*/ | ||
var buster = require('buster') | ||
@@ -12,9 +10,8 @@ , assert = buster.assert | ||
, fs = require('fs') | ||
, common = require('./common') | ||
require('./common.js') | ||
buster.testCase('Binary API', { | ||
'setUp': function (done) { | ||
commonSetUp.call(this) | ||
loadBinaryTestData(function (err, data) { | ||
common.commonSetUp.call(this) | ||
common.loadBinaryTestData(function (err, data) { | ||
refute(err) | ||
@@ -26,7 +23,7 @@ this.testData = data | ||
, 'tearDown': commonTearDown | ||
, 'tearDown': common.commonTearDown | ||
, 'sanity check on test data': function (done) { | ||
assert(Buffer.isBuffer(this.testData)) | ||
checkBinaryTestData(this.testData, done) | ||
common.checkBinaryTestData(this.testData, done) | ||
} | ||
@@ -41,3 +38,3 @@ | ||
assert(value) | ||
checkBinaryTestData(value, done) | ||
common.checkBinaryTestData(value, done) | ||
}) | ||
@@ -55,3 +52,3 @@ }) | ||
assert(value) | ||
checkBinaryTestData(value, done) | ||
common.checkBinaryTestData(value, done) | ||
}) | ||
@@ -82,3 +79,3 @@ }) | ||
assert(value) | ||
checkBinaryTestData(value, done) | ||
common.checkBinaryTestData(value, done) | ||
}) | ||
@@ -96,3 +93,3 @@ }) | ||
assert(value) | ||
checkBinaryTestData(value, done) | ||
common.checkBinaryTestData(value, done) | ||
}) | ||
@@ -122,3 +119,3 @@ }) | ||
refute(err) | ||
checkBinaryTestData(value, done) | ||
common.checkBinaryTestData(value, done) | ||
}.bind(this)) | ||
@@ -166,3 +163,3 @@ }.bind(this)) | ||
} else { | ||
checkBinaryTestData(value, callback) | ||
common.checkBinaryTestData(value, callback) | ||
} | ||
@@ -169,0 +166,0 @@ }) |
@@ -34,19 +34,22 @@ /* Copyright (c) 2012 Rod Vagg <@rvagg> */ | ||
global.openTestDatabase = function () { | ||
module.exports.nextLocation = function () { | ||
return path.join(__dirname, 'levelup_test_db_' + dbidx++) | ||
} | ||
module.exports.openTestDatabase = function () { | ||
var options = typeof arguments[0] == 'object' ? arguments[0] : { createIfMissing: true, errorIfExists: true } | ||
, callback = typeof arguments[0] == 'function' ? arguments[0] : arguments[1] | ||
, location = typeof arguments[0] == 'string' ? arguments[0] : path.join(__dirname, 'levelup_test_db_' + dbidx++) | ||
, location = typeof arguments[0] == 'string' ? arguments[0] : module.exports.nextLocation() | ||
rimraf(location, function (err) { | ||
refute(err) | ||
this.cleanupDirs.push(location) | ||
var db = levelup.createDatabase(location, options) | ||
this.closeableDatabases.push(db) | ||
db.open(function (err) { | ||
levelup(location, options, function (err, db) { | ||
refute(err) | ||
this.closeableDatabases.push(db) | ||
callback(db) | ||
}) | ||
}.bind(this)) | ||
}.bind(this)) | ||
} | ||
global.commonTearDown = function (done) { | ||
module.exports.commonTearDown = function (done) { | ||
async.forEach( | ||
@@ -63,9 +66,9 @@ this.closeableDatabases | ||
global.loadBinaryTestData = function (callback) { | ||
fs.readFile(path.join(__dirname, 'testdata.bin'), callback) | ||
module.exports.loadBinaryTestData = function (callback) { | ||
fs.readFile(path.join(__dirname, 'data/testdata.bin'), callback) | ||
} | ||
global.binaryTestDataMD5Sum = '920725ef1a3b32af40ccd0b78f4a62fd' | ||
module.exports.binaryTestDataMD5Sum = '920725ef1a3b32af40ccd0b78f4a62fd' | ||
global.checkBinaryTestData = function (testData, callback) { | ||
module.exports.checkBinaryTestData = function (testData, callback) { | ||
var fname = '__tst.dat.' + Math.random() | ||
@@ -79,3 +82,3 @@ fs.writeFile(fname, testData, function (err) { | ||
var md5Sum = stdout.split(' ')[0] | ||
assert.equals(md5Sum, global.binaryTestDataMD5Sum) | ||
assert.equals(md5Sum, module.exports.binaryTestDataMD5Sum) | ||
fs.unlink(fname, callback) | ||
@@ -87,7 +90,7 @@ }) | ||
global.commonSetUp = function () { | ||
module.exports.commonSetUp = function () { | ||
this.cleanupDirs = [] | ||
this.closeableDatabases = [] | ||
this.openTestDatabase = global.openTestDatabase.bind(this) | ||
this.openTestDatabase = module.exports.openTestDatabase.bind(this) | ||
this.timeout = 1000 | ||
} |
/* Copyright (c) 2012 Rod Vagg <@rvagg> */ | ||
/*global commonSetUp:true, commonTearDown:true*/ | ||
var buster = require('buster') | ||
@@ -12,6 +10,7 @@ , assert = buster.assert | ||
, fs = require('fs') | ||
, common = require('./common') | ||
buster.testCase('Copy', { | ||
'setUp': commonSetUp | ||
, 'tearDown': commonTearDown | ||
'setUp': common.commonSetUp | ||
, 'tearDown': common.commonTearDown | ||
@@ -18,0 +17,0 @@ , 'copy full database': function (done) { |
/* Copyright (c) 2012 Rod Vagg <@rvagg> */ | ||
/*global commonSetUp:true, commonTearDown:true*/ | ||
var buster = require('buster') | ||
@@ -13,6 +11,7 @@ , assert = buster.assert | ||
, path = require('path') | ||
, common = require('./common') | ||
buster.testCase('ReadStream', { | ||
'setUp': function () { | ||
commonSetUp.call(this) | ||
common.commonSetUp.call(this) | ||
@@ -24,6 +23,7 @@ this.readySpy = this.spy() | ||
for (var i = 0; i < 10; i++) { | ||
for (var i = 0; i < 100; i++) { | ||
var k = (i < 10 ? '0' : '') + i | ||
this.sourceData.push({ | ||
type : 'put' | ||
, key : i | ||
, key : k | ||
, value : Math.random() | ||
@@ -53,3 +53,3 @@ }) | ||
, 'tearDown': commonTearDown | ||
, 'tearDown': common.commonTearDown | ||
@@ -75,36 +75,2 @@ //TODO: test various encodings | ||
, 'test delayed open': function (done) { | ||
var location = path.join(__dirname, 'levelup_test_db_delayed_open') | ||
, execute = function () { | ||
this.cleanupDirs.push(location) | ||
var db = levelup.createDatabase(location | ||
, { createIfMissing: true, errorIfExists: false } | ||
) | ||
this.closeableDatabases.push(db) | ||
db.open(function (err) { | ||
refute(err) | ||
var rs = db.readStream() | ||
assert.isFalse(rs.writable) | ||
assert.isTrue(rs.readable) | ||
rs.on('ready', this.readySpy) | ||
rs.on('data' , this.dataSpy) | ||
rs.on('end' , this.endSpy) | ||
rs.on('close', this.verify.bind(this, rs, done)) | ||
}.bind(this)) | ||
}.bind(this) | ||
// setup -- open db, write stuff to it, close it again so we can reopen it | ||
this.openTestDatabase(location, function (db) { | ||
db.batch(this.sourceData.slice(), function (err) { | ||
refute(err) | ||
db.close(function () { | ||
setTimeout(function () { | ||
execute() | ||
}, 10) | ||
}) | ||
}) | ||
}.bind(this)) | ||
} | ||
, 'test pausing': function (done) { | ||
@@ -126,3 +92,3 @@ var calls = 0 | ||
, verify = function () { | ||
assert.equals(calls, 10, 'onData was used in test') | ||
assert.equals(calls, this.sourceData.length, 'onData was used in test') | ||
assert(pauseVerify.called, 'pauseVerify was used in test') | ||
@@ -214,2 +180,99 @@ this.verify(rs, done) | ||
} | ||
, 'test readStream() with "start"': function (done) { | ||
this.openTestDatabase(function (db) { | ||
db.batch(this.sourceData.slice(), function (err) { | ||
refute(err) | ||
var rs = db.readStream({ start: '50' }) | ||
assert.isFalse(rs.writable) | ||
assert.isTrue(rs.readable) | ||
rs.on('ready', this.readySpy) | ||
rs.on('data' , this.dataSpy) | ||
rs.on('end' , this.endSpy) | ||
rs.on('close', this.verify.bind(this, rs, done)) | ||
// slice off the first 50 so verify() expects only the last 50 even though all 100 are in the db | ||
this.sourceData = this.sourceData.slice(50) | ||
}.bind(this)) | ||
}.bind(this)) | ||
} | ||
, 'test readStream() with "start" being mid-way key (float)': function (done) { | ||
this.openTestDatabase(function (db) { | ||
db.batch(this.sourceData.slice(), function (err) { | ||
refute(err) | ||
// '49.5' doesn't actually exist but we expect it to start at '50' because '49' < '49.5' < '50' (in string terms as well as numeric) | ||
var rs = db.readStream({ start: '49.5' }) | ||
assert.isFalse(rs.writable) | ||
assert.isTrue(rs.readable) | ||
rs.on('ready', this.readySpy) | ||
rs.on('data' , this.dataSpy) | ||
rs.on('end' , this.endSpy) | ||
rs.on('close', this.verify.bind(this, rs, done)) | ||
// slice off the first 50 so verify() expects only the last 50 even though all 100 are in the db | ||
this.sourceData = this.sourceData.slice(50) | ||
}.bind(this)) | ||
}.bind(this)) | ||
} | ||
, 'test readStream() with "start" being mid-way key (string)': function (done) { | ||
this.openTestDatabase(function (db) { | ||
db.batch(this.sourceData.slice(), function (err) { | ||
refute(err) | ||
// '499999' doesn't actually exist but we expect it to start at '50' because '49' < '499999' < '50' (in string terms) | ||
// the same as the previous test but we're relying solely on string ordering | ||
var rs = db.readStream({ start: '499999' }) | ||
assert.isFalse(rs.writable) | ||
assert.isTrue(rs.readable) | ||
rs.on('ready', this.readySpy) | ||
rs.on('data' , this.dataSpy) | ||
rs.on('end' , this.endSpy) | ||
rs.on('close', this.verify.bind(this, rs, done)) | ||
// slice off the first 50 so verify() expects only the last 50 even though all 100 are in the db | ||
this.sourceData = this.sourceData.slice(50) | ||
}.bind(this)) | ||
}.bind(this)) | ||
} | ||
, 'test readStream() with "end"': function (done) { | ||
this.openTestDatabase(function (db) { | ||
db.batch(this.sourceData.slice(), function (err) { | ||
refute(err) | ||
var rs = db.readStream({ end: '50' }) | ||
assert.isFalse(rs.writable) | ||
assert.isTrue(rs.readable) | ||
rs.on('ready', this.readySpy) | ||
rs.on('data' , this.dataSpy) | ||
rs.on('end' , this.endSpy) | ||
rs.on('close', this.verify.bind(this, rs, done)) | ||
// slice off the last 50 so verify() expects only the first 50 even though all 100 are in the db | ||
this.sourceData = this.sourceData.slice(0, 50) | ||
}.bind(this)) | ||
}.bind(this)) | ||
} | ||
, 'test readStream() with both "start" and "end"': function (done) { | ||
this.openTestDatabase(function (db) { | ||
db.batch(this.sourceData.slice(), function (err) { | ||
refute(err) | ||
var rs = db.readStream({ start: 30, end: 70 }) | ||
assert.isFalse(rs.writable) | ||
assert.isTrue(rs.readable) | ||
rs.on('ready', this.readySpy) | ||
rs.on('data' , this.dataSpy) | ||
rs.on('end' , this.endSpy) | ||
rs.on('close', this.verify.bind(this, rs, done)) | ||
this.sourceData = this.sourceData.slice(30, 70) | ||
}.bind(this)) | ||
}.bind(this)) | ||
} | ||
}) |
/* Copyright (c) 2012 Rod Vagg <@rvagg> */ | ||
/*global commonSetUp:true, commonTearDown:true*/ | ||
var buster = require('buster') | ||
@@ -12,61 +10,74 @@ , assert = buster.assert | ||
, fs = require('fs') | ||
, common = require('./common') | ||
buster.testCase('Basic API', { | ||
'setUp': commonSetUp | ||
, 'tearDown': commonTearDown | ||
'setUp': common.commonSetUp | ||
, 'tearDown': common.commonTearDown | ||
, 'createDatabase()': function () { | ||
var db | ||
assert.isFunction(levelup.createDatabase) | ||
assert.equals(levelup.createDatabase.length, 2) // location & options arguments | ||
assert.exception(levelup.createDatabase, 'InitializationError') // no location | ||
, 'levelup()': function () { | ||
assert.isFunction(levelup) | ||
assert.equals(levelup.length, 3) // location, options & callback arguments | ||
assert.exception(levelup, 'InitializationError') // no location | ||
} | ||
db = levelup.createDatabase('/tmp/testdb') | ||
assert.isObject(db) | ||
assert.isFalse(db.options.createIfMissing) | ||
assert.isFalse(db.options.errorIfExists) | ||
assert.equals(db.location, '/tmp/testdb') | ||
, 'default options': function (done) { | ||
var location = common.nextLocation() | ||
levelup(location, { createIfMissing: true, errorIfExists: true }, function (err, db) { | ||
refute(err) | ||
assert.isTrue(db.isOpen()) | ||
this.closeableDatabases.push(db) | ||
this.cleanupDirs.push(location) | ||
db.close(function (err) { | ||
refute(err) | ||
// read-only properties | ||
db.location = 'foo' | ||
assert.equals(db.location, '/tmp/testdb') | ||
assert.isFalse(db.isOpen()) | ||
// with options | ||
db = levelup.createDatabase('/tmp/foodb', { | ||
createIfMissing : true | ||
, errorIfExists : true | ||
}) | ||
assert.isObject(db) | ||
assert.isTrue(db.options.createIfMissing) | ||
assert.isTrue(db.options.errorIfExists) | ||
assert.equals(db.location, '/tmp/foodb') | ||
levelup(location, function (err, db) { // no options object | ||
refute(err) | ||
assert.isObject(db) | ||
assert.isFalse(db.options.createIfMissing) | ||
assert.isFalse(db.options.errorIfExists) | ||
assert.equals(db.location, location) | ||
// read-only properties | ||
db.location = 'bar' | ||
assert.equals(db.location, '/tmp/foodb') | ||
// read-only properties | ||
db.location = 'foo' | ||
assert.equals(db.location, location) | ||
done() | ||
}.bind(this)) | ||
}.bind(this)) | ||
}.bind(this)) | ||
} | ||
, 'open() with !createIfMissing expects error': function (done) { | ||
var db = levelup.createDatabase(this.cleanupDirs[0] = '/tmp/levelup_test_db') | ||
, 'basic options': function (done) { | ||
var location = common.nextLocation() | ||
levelup(location, { createIfMissing: true, errorIfExists: true }, function (err, db) { | ||
refute(err) | ||
this.closeableDatabases.push(db) | ||
this.cleanupDirs.push(location) | ||
assert.isObject(db) | ||
assert.isTrue(db.options.createIfMissing) | ||
assert.isTrue(db.options.errorIfExists) | ||
assert.equals(db.location, location) | ||
assert.isFalse(db.isOpen()) | ||
// read-only properties | ||
db.location = 'bar' | ||
assert.equals(db.location, location) | ||
done() | ||
}.bind(this)) | ||
} | ||
db.open(function (err) { | ||
, 'open() with !createIfMissing expects error': function (done) { | ||
levelup(this.cleanupDirs[0] = common.nextLocation(), function (err, db) { | ||
assert(err) | ||
refute(db) | ||
assert.isInstanceOf(err, Error) | ||
assert.isInstanceOf(err, errors.LevelUPError) | ||
assert.isInstanceOf(err, errors.OpenError) | ||
assert.isFalse(db.isOpen()) | ||
done() | ||
}) | ||
}.bind(this)) | ||
} | ||
, 'open() with createIfMissing expects directory to be created': function (done) { | ||
var db = levelup.createDatabase( | ||
this.cleanupDirs[0] = '/tmp/levelup_test_db' | ||
, { createIfMissing: true } | ||
) | ||
this.closeableDatabases.push(db) | ||
db.open(function (err) { | ||
levelup(this.cleanupDirs[0] = common.nextLocation(), { createIfMissing: true }, function (err, db) { | ||
this.closeableDatabases.push(db) | ||
refute(err) | ||
@@ -83,15 +94,7 @@ assert.isTrue(db.isOpen()) | ||
, 'open() with errorIfExists expects error if exists': function (done) { | ||
var db = levelup.createDatabase( | ||
this.cleanupDirs[0] = '/tmp/levelup_test_db' | ||
, { createIfMissing: true } | ||
) | ||
this.closeableDatabases.push(db) | ||
db.open(function (err) { | ||
levelup(this.cleanupDirs[0] = common.nextLocation(), { createIfMissing: true }, function (err, db) { | ||
this.closeableDatabases.push(db) | ||
refute(err) // sanity | ||
var db = levelup.createDatabase( | ||
this.cleanupDirs[0] | ||
, { errorIfExists : true } | ||
) | ||
db.open(function (err) { | ||
levelup(this.cleanupDirs[0], { errorIfExists : true }, function (err) { | ||
assert(err) | ||
assert.isInstanceOf(err, Error) | ||
@@ -106,10 +109,5 @@ assert.isInstanceOf(err, errors.LevelUPError) | ||
, 'open() with !errorIfExists does not expect error if exists': function (done) { | ||
var db = levelup.createDatabase( | ||
this.cleanupDirs[0] = '/tmp/levelup_test_db' | ||
, { createIfMissing: true } | ||
) | ||
this.closeableDatabases.push(db) | ||
db.open(function (err) { | ||
levelup(this.cleanupDirs[0] = common.nextLocation(), { createIfMissing: true }, function (err, db) { | ||
refute(err) // sanity | ||
this.closeableDatabases.push(db) | ||
assert.isTrue(db.isOpen()) | ||
@@ -120,12 +118,8 @@ | ||
db = levelup.createDatabase( | ||
this.cleanupDirs[0] | ||
, { errorIfExists : false } | ||
) | ||
this.closeableDatabases.push(db) | ||
db.open(function (err) { | ||
levelup(this.cleanupDirs[0], { errorIfExists : false }, function (err, db) { | ||
refute(err) | ||
this.closeableDatabases.push(db) | ||
assert.isTrue(db.isOpen()) | ||
done() | ||
}) | ||
}.bind(this)) | ||
}.bind(this)) | ||
@@ -137,21 +131,36 @@ }.bind(this)) | ||
'get() on non-open database causes error': function (done) { | ||
levelup.createDatabase('foobar').get('undefkey', function (err, value) { | ||
refute(value) | ||
assert.isInstanceOf(err, Error) | ||
assert.isInstanceOf(err, errors.LevelUPError) | ||
assert.isInstanceOf(err, errors.ReadError) | ||
assert.match(err, /not .*open/) | ||
done() | ||
}) | ||
levelup(this.cleanupDirs[0] = common.nextLocation(), { createIfMissing: true }, function (err, db) { | ||
refute(err) // sanity | ||
this.closeableDatabases.push(db) | ||
assert.isTrue(db.isOpen()) | ||
db.close(function () { | ||
db.get('undefkey', function (err, value) { | ||
refute(value) | ||
assert.isInstanceOf(err, Error) | ||
assert.isInstanceOf(err, errors.LevelUPError) | ||
assert.isInstanceOf(err, errors.ReadError) | ||
assert.match(err, /not .*open/) | ||
done() | ||
}) | ||
}) | ||
}.bind(this)) | ||
} | ||
, 'put() on non-open database causes error': function (done) { | ||
levelup.createDatabase('foobar').put('somekey', 'somevalue', function (err, value) { | ||
refute(value) | ||
assert.isInstanceOf(err, Error) | ||
assert.isInstanceOf(err, errors.LevelUPError) | ||
assert.isInstanceOf(err, errors.WriteError) | ||
assert.match(err, /not .*open/) | ||
done() | ||
}) | ||
levelup(this.cleanupDirs[0] = common.nextLocation(), { createIfMissing: true }, function (err, db) { | ||
refute(err) // sanity | ||
this.closeableDatabases.push(db) | ||
assert.isTrue(db.isOpen()) | ||
db.close(function () { | ||
db.put('somekey', 'somevalue', function (err) { | ||
assert.isInstanceOf(err, Error) | ||
assert.isInstanceOf(err, errors.LevelUPError) | ||
assert.isInstanceOf(err, errors.WriteError) | ||
assert.match(err, /not .*open/) | ||
done() | ||
}) | ||
}) | ||
}.bind(this)) | ||
} | ||
@@ -186,9 +195,17 @@ | ||
, 'del() on non-open database causes error': function (done) { | ||
levelup.createDatabase('foobar').del('undefkey', function (err) { | ||
assert.isInstanceOf(err, Error) | ||
assert.isInstanceOf(err, errors.LevelUPError) | ||
assert.isInstanceOf(err, errors.WriteError) | ||
assert.match(err, /not .*open/) | ||
done() | ||
}) | ||
levelup(this.cleanupDirs[0] = common.nextLocation(), { createIfMissing: true }, function (err, db) { | ||
refute(err) // sanity | ||
this.closeableDatabases.push(db) | ||
assert.isTrue(db.isOpen()) | ||
db.close(function () { | ||
db.del('undefkey', function (err) { | ||
assert.isInstanceOf(err, Error) | ||
assert.isInstanceOf(err, errors.LevelUPError) | ||
assert.isInstanceOf(err, errors.WriteError) | ||
assert.match(err, /not .*open/) | ||
done() | ||
}) | ||
}) | ||
}.bind(this)) | ||
} | ||
@@ -195,0 +212,0 @@ |
/* Copyright (c) 2012 Rod Vagg <@rvagg> */ | ||
/*global commonSetUp:true, commonTearDown:true*/ | ||
var buster = require('buster') | ||
@@ -13,6 +11,7 @@ , assert = buster.assert | ||
, path = require('path') | ||
, common = require('./common') | ||
buster.testCase('WriteStream', { | ||
'setUp': function () { | ||
commonSetUp.call(this) | ||
common.commonSetUp.call(this) | ||
@@ -48,3 +47,3 @@ this.timeout = 1000 | ||
, 'tearDown': commonTearDown | ||
, 'tearDown': common.commonTearDown | ||
@@ -96,33 +95,2 @@ //TODO: test various encodings | ||
, 'test delayed open with maxBufferLength': function (done) { | ||
var location = path.join(__dirname, 'levelup_test_db_delayed_open') | ||
this.cleanupDirs.push(location) | ||
var db = levelup.createDatabase( | ||
location | ||
, { createIfMissing: true, errorIfExists: false } | ||
) | ||
, ws = db.writeStream({ maxBufferLength: 1 }) | ||
this.closeableDatabases.push(db) | ||
// should be able to push first element in just fine | ||
assert.isTrue(ws.write(this.sourceData[0])) | ||
// second element should warn that the buffer isn't being cleared | ||
assert.isFalse(ws.write(this.sourceData[1])) | ||
ws.once('close', this.verify.bind(this, ws, db, done)) | ||
ws.once('drain', function () { | ||
this.sourceData.slice(2).forEach(function (d, i) { | ||
assert[i !== 0 ? 'isFalse' : 'isTrue'](ws.write(d), 'correct return value for element #' + i) | ||
}) | ||
assert.isTrue(ws.writable) | ||
assert.isFalse(ws.readable) | ||
ws.end() | ||
}.bind(this)) | ||
db.open(function (err) { | ||
// should lead to a 'drain' event | ||
refute(err) | ||
}) | ||
} | ||
// at the moment, destroySoon() is basically just end() | ||
@@ -129,0 +97,0 @@ , 'test destroySoon()': function (done) { |
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
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
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
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
Non-existent author
Supply chain riskThe package was published by an npm account that no longer exists.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
2880537
222
1945
165
0
4
9
4
+ Addedbufferstream@~0.5.1
+ Addedbufferstream@0.5.2(transitive)
+ Addedbuffertools@2.1.6(transitive)
+ Addedconcat-stream@0.0.9(transitive)
+ Addederrno@0.0.5(transitive)
- Removedbuffer-from@1.1.2(transitive)
- Removedconcat-stream@2.0.0(transitive)
- Removederrno@1.0.0(transitive)
- Removedinherits@2.0.4(transitive)
- Removedprr@1.0.1(transitive)
- Removedreadable-stream@3.6.2(transitive)
- Removedsafe-buffer@5.2.1(transitive)
- Removedstring_decoder@1.3.0(transitive)
- Removedtypedarray@0.0.6(transitive)
- Removedutil-deprecate@1.0.2(transitive)
Updatedconcat-stream@~0.0.8
Updatederrno@~0.0.2