level-updown
Version:
LevelDOWN backed by LevelUP
276 lines (198 loc) • 6.48 kB
JavaScript
var AbstractLevelDOWN = require('abstract-leveldown').AbstractLevelDOWN
, AbstractIterator = require('abstract-leveldown').AbstractIterator
, inherits = require('util').inherits
, EventEmitter = require('events').EventEmitter
, externr = require('externr')
, xtend = require('xtend')
function fixOptions (options) {
var x = {}
if (options.asBuffer != null)
x.valueEncoding = options.asBuffer ? 'binary' : 'utf8'
else if (!options.valueEncoding)
x.valueEncoding = 'binary'
if (options.keyEncoding != 'utf8' && options.valueEncoding != 'utf8')
x.keyEncoding = 'binary'
return xtend(options, x)
}
function LevelUPDOWNIterator (db, options) {
if (!(this instanceof LevelUPDOWNIterator))
return new LevelUPDOWNIterator(db, options)
AbstractIterator.call(this, db)
this.options = options
this._externs = externr({ wrap: [ 'preNext', 'postNext', 'preEnd', 'postEnd' ] })
this.extendWith = this._externs.$register.bind(this._externs)
var self = this
function start () {
self._iterator = self.db.levelup.db.iterator(options)
}
if (db.levelup.isOpen())
return start()
this._deferred = new EventEmitter()
db.levelup.once('ready', function () {
start()
setImmediate(function () {
self._deferred.emit('ready')
self._deferred = null
})
})
}
inherits(LevelUPDOWNIterator, AbstractIterator)
LevelUPDOWNIterator.prototype._next = function (callback) {
var self = this
function exec () {
self._externs.preNext(self, [ callback ], afterPreNext)
function afterPreNext (callback) {
self._iterator.next(afterNext)
function afterNext (err, key, value) {
self._externs.postNext(self, [ err, key, value, callback ], afterPostNext)
}
function afterPostNext (err, key, value, callback) {
if (!err && !key && !value)
return callback()
callback(err, key, value)
}
}
}
if (!this._deferred)
return exec()
this._deferred.on('ready', exec)
}
LevelUPDOWNIterator.prototype._end = function (callback) {
var self = this
function exec () {
self._externs.preEnd(self, [ callback ], afterPreEnd)
function afterPreEnd (callback) {
self._iterator.end(afterEnd)
function afterEnd (err) {
self._externs.postEnd(self, [ err, callback ], afterPostEnd)
}
function afterPostEnd (err, callback) {
callback(err)
}
}
}
if (!this._deferred)
return exec()
this._deferred.on('ready', exec)
}
function LevelUPDOWN (levelup) {
if (!(this instanceof LevelUPDOWN))
return new LevelUPDOWN(levelup)
AbstractLevelDOWN.call(this, '')
this.levelup = levelup
this._externs = externr({
wrap : [
'open'
, 'close'
, 'prePut'
, 'postPut'
, 'preGet'
, 'postGet'
, 'preDel'
, 'postDel'
, 'preBatch'
, 'postBatch'
]
, extend : [
'preIterator'
, 'postIterator'
]
})
this.extendWith = this._externs.$register.bind(this._externs)
}
inherits(LevelUPDOWN, AbstractLevelDOWN)
// noop
LevelUPDOWN.prototype._open = function (options, callback) {
this._externs.open(this, [ options, callback ], afterOpen)
function afterOpen (options, callback) {
process.nextTick(callback)
}
}
// noop
LevelUPDOWN.prototype._close = function (callback) {
this._externs.close(this, [ callback ], afterClose)
function afterClose (callback) {
process.nextTick(callback)
}
}
LevelUPDOWN.prototype._put = function (key, value, options, callback) {
var self = this
this._externs.prePut(this, [ key, value, options, callback ], afterPrePut)
function afterPrePut (key, value, options, callback) {
options = xtend(options)
delete options.valueEncoding
self.levelup.put(key, value, options, afterPut)
function afterPut (err) {
self._externs.postPut(self, [ key, value, options, err, callback ], afterPostPut)
}
function afterPostPut (key, value, options, err, callback) {
callback(err)
}
}
}
LevelUPDOWN.prototype._get = function (key, options, callback) {
var self = this
this._externs.preGet(this, [ key, options, callback ], afterPreGet)
function afterPreGet (key, options, callback) {
options = xtend(options)
delete options.valueEncoding
self.levelup.get(key, fixOptions(options), afterGet)
function afterGet (err, value) {
self._externs.postGet(self, [ key, options, err, value, callback ], afterPostGet)
}
function afterPostGet (key, options, err, value, callback) {
callback(err, value)
}
}
}
LevelUPDOWN.prototype._del = function (key, options, callback) {
var self = this
this._externs.preDel(this, [ key, options, callback ], afterPreDel)
function afterPreDel (key, options, callback) {
self.levelup.del(key, options, afterDel)
function afterDel (err) {
self._externs.postDel(self, [ key, options, err, callback ], afterPostDel)
}
function afterPostDel (key, options, err, callback) {
callback(err)
}
}
}
LevelUPDOWN.prototype._batch = function (array, options, callback) {
var self = this
this._externs.preBatch(this, [ array, options, callback ], afterPreBatch)
function afterPreBatch (array, options, callback) {
options = xtend(options)
delete options.valueEncoding
self.levelup.batch(array, options, afterBatch)
function afterBatch (err) {
self._externs.postBatch(self, [ array, options, err, callback ], afterPostBatch)
}
function afterPostBatch (array, options, err, callback) {
callback(err)
}
}
}
LevelUPDOWN.prototype._iterator = function (options) {
var self = this
function iteratorFactory (options) {
var iterator = new LevelUPDOWNIterator(self, fixOptions(options))
return self._externs.postIterator(iterator)
}
var pre = self._externs.preIterator({
options : options
, factory : iteratorFactory
})
return pre.factory(pre.options)
}
LevelUPDOWN.prototype._isBuffer = function (obj) {
return Buffer.isBuffer(obj)
}
module.exports = LevelUPDOWN
module.exports.LevelUPDOWNIterator = LevelUPDOWNIterator
module.exports.factory = function factory () {
var args = Array.prototype.slice.call(arguments)
return function makeLevelUPDOWN () {
return LevelUPDOWN.apply(null, args)
}
}