You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
4.4 KiB

var EventEmitter = require('events').EventEmitter
var addpre = require('./range').addPrefix
var errors = require('levelup/lib/errors')
function isFunction (f) {
return 'function' === typeof f
}
function isString (s) {
return 'string' === typeof s
}
function isObject (o) {
return o && 'object' === typeof o
}
var version = require('./package.json').version
var sublevel = module.exports = function (nut, prefix, createStream, options) {
var emitter = new EventEmitter()
emitter.sublevels = {}
emitter.options = options
emitter.version = version
emitter.methods = {}
prefix = prefix || []
function errback (err) { if (err) emitter.emit('error', err) }
createStream = createStream || function (e) { return e }
function mergeOpts(opts) {
var o = {}
if(options)
for(var k in options)
if(options[k] != undefined)o[k] = options[k]
if(opts)
for(var k in opts)
if(opts[k] != undefined) o[k] = opts[k]
return o
}
emitter.put = function (key, value, opts, cb) {
if('function' === typeof opts) cb = opts, opts = {}
if(!cb) cb = errback
nut.apply([{
key: key, value: value,
prefix: prefix.slice(), type: 'put'
}], mergeOpts(opts), function (err) {
if(!err) { emitter.emit('put', key, value); cb(null) }
if(err) return cb(err)
})
}
emitter.prefix = function () {
return prefix.slice()
}
emitter.del = function (key, opts, cb) {
if('function' === typeof opts) cb = opts, opts = {}
if(!cb) cb = errback
nut.apply([{
key: key,
prefix: prefix.slice(), type: 'del'
}], mergeOpts(opts), function (err) {
if(!err) { emitter.emit('del', key); cb(null) }
if(err) return cb(err)
})
}
emitter.batch = function (ops, opts, cb) {
if('function' === typeof opts)
cb = opts, opts = {}
if(!cb) cb = errback
ops = ops.map(function (op) {
return {
key: op.key,
value: op.value,
prefix: op.prefix || prefix,
keyEncoding: op.keyEncoding, // *
valueEncoding: op.valueEncoding, // * (TODO: encodings on sublevel)
type: op.type
}
})
nut.apply(ops, mergeOpts(opts), function (err) {
if(!err) { emitter.emit('batch', ops); cb(null) }
if(err) return cb(err)
})
}
emitter.get = function (key, opts, cb) {
if('function' === typeof opts)
cb = opts, opts = {}
nut.get(key, prefix, mergeOpts(opts), function (err, value) {
if(err) cb(new errors.NotFoundError('Key not found in database', err))
else cb(null, value)
})
}
emitter.clone = function(opts) {
return sublevel(nut, prefix, createStream, mergeOpts(opts))
}
emitter.sublevel = function (name, opts) {
return emitter.sublevels[name] =
emitter.sublevels[name] || sublevel(nut, prefix.concat(name), createStream, mergeOpts(opts))
}
emitter.pre = function (key, hook) {
if(isFunction(key)) return nut.pre([prefix], key)
if(isString(key)) return nut.pre([prefix, key], hook)
if(isObject(key)) return nut.pre(addpre(prefix, key), hook)
throw new Error('not implemented yet')
}
emitter.post = function (key, hook) {
if(isFunction(key)) return nut.post([prefix], key)
if(isString(key)) return nut.post([prefix, key], hook)
if(isObject(key)) return nut.post(addpre(prefix, key), hook)
//TODO: handle ranges, needed for level-live-stream, etc.
throw new Error('not implemented yet')
}
emitter.readStream =
emitter.createReadStream = function (opts) {
opts = mergeOpts(opts)
opts.prefix = prefix
var stream
var it = nut.iterator(opts, function (err, it) {
stream.setIterator(it)
})
stream = createStream(opts, nut.createDecoder(opts))
if(it) stream.setIterator(it)
return stream
}
emitter.valueStream =
emitter.createValueStream = function (opts) {
opts = opts || {}
opts.values = true
opts.keys = false
return emitter.createReadStream(opts)
}
emitter.keyStream =
emitter.createKeyStream = function (opts) {
opts = opts || {}
opts.values = false
opts.keys = true
return emitter.createReadStream(opts)
}
emitter.close = function (cb) {
//TODO: deregister all hooks
cb = cb || function () {}
if (!prefix.length) nut.close(cb)
else process.nextTick(cb)
}
emitter.isOpen = nut.isOpen
emitter.isClosed = nut.isClosed
emitter.location = nut.location
return emitter
}