[
  {
    "path": ".gitignore",
    "content": "node_modules\ntest/db\n*.sw*\nexample/.db\ntest/node/manifest.json"
  },
  {
    "path": ".travis.yml",
    "content": "sudo: false\n\nlanguage: node_js\n\nnode_js:\n  - \"4.0\"\n  - \"3.0\"\n  - \"2.4\"\n  - \"1.8\"\n  - \"1.0\"\n  - \"0.12\"\n"
  },
  {
    "path": "History.md",
    "content": "\n6.0.1 / 2014-08-18 \n==================\n\n * use npm version of rpc-stream\n * docs\n * make benchmarks runnable\n * add history\n * assert read stream close immediately after conn error\n * close read/write streams on connection failure\n\n6.0.0 / 2014-04-28 \n==================\n\n * add event specialcasing\n * docs\n"
  },
  {
    "path": "Makefile",
    "content": "\nBIN=node_modules/.bin\n\ntest:\n\t@$(BIN)/tape test/*.js test/node/*.js\n\ntest-browser:\n\t@echo \"open http://localhost:9000/\"\n\t@$(BIN)/browserify test/*.js | $(BIN)/browser-run --port 9000\"\n\n.PHONY: test test-browser\n\n"
  },
  {
    "path": "README.md",
    "content": "# multilevel\n\nExpose a levelDB over the network, to be used by multiple processes,\nwith [levelUp](https://github.com/rvagg/node-levelup)'s API.\n\n[![Build Status](https://travis-ci.org/juliangruber/multilevel.svg?branch=master)](https://travis-ci.org/juliangruber/multilevel)\n[![downloads](https://img.shields.io/npm/dm/multilevel.svg)](https://www.npmjs.org/package/multilevel)\n\n## Usage\n\nExpose a db on the server:\n\n```js\nvar multilevel = require('multilevel');\nvar net = require('net');\nvar level = require('level');\n\nvar db = level('/my/db');\n\nnet.createServer(function (con) {\n  con.pipe(multilevel.server(db)).pipe(con);\n}).listen(3000);\n```\n\nAnd connect to it from the client:\n\n```js\nvar multilevel = require('multilevel');\nvar net = require('net');\n\nvar db = multilevel.client();\nvar con = net.connect(3000);\ncon.pipe(db.createRpcStream()).pipe(con);\n\n// asynchronous methods\ndb.get('foo', function () { /* */ });\n\n// streams\ndb.createReadStream().on('data', function () { /* */ });\n```\n\n## Compatibility and binary data\n\nmultilevel works in the browser too - via\n[browserify](https://github.com/substack/node-browserify) - and has full\nsupport for binary data. For getting a connection between browser and server I\nrecommend either\n[websocket-stream](https://github.com/maxogden/websocket-stream), which treats\nbinary data well, or\n[engine.io-stream](https://github.com/Raynos/engine.io-stream), which has\nwebsocket fallbacks.\n\nWhen using a binary capable transport, require multilevel like this:\n\n```js\nvar multilevel = require('multilevel/msgpack');\n```\n\nThis way it uses [msgpack-stream](https://github.com/dominictarr/msgpack-stream)\ninstead of [json-buffer](https://github.com/dominictarr/json-buffer) which uses\nway less bandwidth - but needs a binary capable transport.\n\n## Plugins\n\nYou can also expose custom methods and [sublevels](https://github.com/dominictarr/level-sublevel)\nwith `multilevel`!\n\nWhen using plugins, you must generate a manifest and require it in the client.\n\nHere's an example:\n\n``` js\n// server.js\n// create `db`\nvar level = require('level');\nvar multilevel = require('multilevel');\nvar db = level(PATH);\n\n// extend `db` with a foo(cb) method\ndb.methods = db.methods || {};\ndb.methods['foo'] = { type: 'async' };\ndb.foo = function (cb) {\n  cb(null, 'bar');\n};\n\n// now write the manifest to a file\nmultilevel.writeManifest(db, __dirname + '/manifest.json');\n\n// then expose `db` via shoe or any other streaming transport.\nvar shoe = require('shoe');\nvar sock = shoe(function (stream) {\n  stream.pipe(multilevel.server(db)).pipe(stream);\n});\nsock.install(http.createServer(/* ... */), '/websocket');\n```\n\nManifests are generated using\n[level-manifest](https://github.com/dominictarr/level-manifest), which doesn't\nonly support async functions but e.g. streams as well. For more, check its README.\n\nThen require the manifest on the client when bundling with browserify or in\nany other nodejs compatible environment.\n\n``` js\n// client.js\n// instantiate a multilevel client with the `manifest.json` we just generated\nvar multilevel = require('multilevel');\nvar manifest = require('./manifest.json');\nvar db = multilevel.client(manifest);\n\n// now pipe the db to the server\nvar stream = shoe('/websocket');\nstream.pipe(db.createRpcStream()).pipe(stream);\n\n// and you can call the custom `foo` method!\ndb.foo(function (err, res) {\n  console.log(res); // => \"bar\"\n});\n```\n\n## Authentication\n\nYou do not want to expose every database feature to every user, you might e.g.\nonly want to provide read-only access to some users.\n\nAuth controls may be injected when creating the server stream.\n\nIn this example, allow read only access, unless logged in as root.\n\n```js\n//server.js\nvar db = require('./setup-db'); //all your database customizations\nvar multilevel = require('multilevel');\n\n//write out manifest\nmultilevel.writeManifest(db, __dirname + '/manifest.json');\n\nshoe(function (stream) {\n  stream.pipe(multilevel.server(db, {\n    auth: function (user, cb) {\n      if (user.name == 'root' && user.pass == 'toor') {\n        //the data returned will be attached to the mulilevel stream\n        //and passed to `access`\n        cb(null, {name: 'root'});\n      } else {\n        cb(new Error('not authorized');\n      }\n    },\n    access: function (user, db, method, args) {\n      //`user` is the {name: 'root'} object that `auth`\n      //returned. \n\n      //if not a privliged user...\n      if (!user || user.name !== 'root') {\n        //do not allow any write access\n        if (/^put|^del|^batch|write/i.test(method)) {\n          throw new Error('read-only access');\n        }\n      }        \n    })\n  })).pipe(stream);\n});\n\n// ...\n```\n\nThe client authorizes by calling the auth method.\n\n``` js\nvar multilevel = require('multilevel');\nvar shoe = require('shoe');\n\nvar stream = shoe();\nvar db = multilevel.client();\nstream.pipe(db.createRpcStream()).pipe(stream);\n\ndb.auth({ name: 'root', pass: 'toor' }, function (err, data) {\n  if (err) throw err\n  //later, they can sign out, too.\n\n  db.deauth(function (err) {\n    //signed out!\n  });\n});\n```\n\n## API\n\nThe exposed DB has the exact same API as\n[levelUp](https://github.com/rvagg/node-levelup), except\n\n* `db#close()` closes the connection, instead of the database.\n* the synchronous versions of `db#isOpen()` and `db#isClose()` tell you if you\ncurrently have a connection to the remote db.\n* events, like `db.on(\"put\", ...)` are not emitted. If you need updates, you\ncan use [level-live-stream](https://github.com/dominictarr/level-live-stream).\n\n### multilevel.server(db[, authOpts])\n\nReturns a server-stream that exposes `db`, an instance of levelUp.\n`authOpts` is optional and should be of this form:\n\n``` js\nvar authOpts = {\n  auth: function (userData, cb) {\n    //call back an error, if the user is not authorized.\n  },\n  access: function (userData, db, method, args) {\n    //throw if this user is not authorized for this action.\n  }\n}\n```\n\nIt is necessary that you create _one server stream per client_.\n\n### multilevel.writeManifest(db, path)\n\n**Synchronoulsy** write `db`'s manifest to `path`.\n\nAlso returns the manifest as json.\n\n### var db = multilevel.client([manifest])\n\nReturn a new client db. `manifest` may optionally be provided, which will\ngrant the client access to extensions and sublevels.\n\n#### db.createRpcStream()\n\nPipe this into a server stream.\n\nListen for the `error` event on this stream to handle / swallow reconnect events.\n\n#### db.auth(data, cb)\n\nAuthorize with the server.\n\n#### db.deauth (cb)\n\nDeauthorize with the server.\n\n## Performance\n\nOn my macbook pro one multilevel server handles ~15k ops/s over a local tcp\nsocket.\n\n```js\n ∴  bench (master) : node index.js \n\nwriting \"1234567890abcdef\" 100 times\n\n native             : 2ms (50000 ops/s)\n multilevel direct  : 21ms (4762 ops/s)\n multilevel network : 14ms (7143 ops/s)\n\nwriting \"1234567890abcdef\" 1000 times\n\n native             : 12ms (83333 ops/s)\n multilevel direct  : 71ms (14085 ops/s)\n multilevel network : 77ms (12987 ops/s)\n\nwriting \"1234567890abcdef\" 10000 times\n\n native             : 88ms (113636 ops/s)\n multilevel direct  : 594ms (16835 ops/s)\n multilevel network : 590ms (16949 ops/s)\n\nwriting \"1234567890abcdef\" 100000 times\n\n native             : 927ms (107875 ops/s)\n multilevel direct  : 10925ms (9153 ops/s)\n multilevel network : 9839ms (10164 ops/s)\n```\n\n## Installation\n\nWith [npm](http://npmjs.org) do:\n\n```bash\n$ npm install multilevel\n```\n\n## Contributing\n\n```bash\n$ npm install\n$ npm test\n$ npm run test-browser\n```\n\n## Contributors\n\n* [@juliangruber](https://github.com/juliangruber)\n* [@dominictarr](https://github.com/dominictarr)\n\n## Sponsors\n\nThis module is proudly supported by my [Sponsors](https://github.com/juliangruber/sponsors)!\n\nDo you want to support modules like this to improve their quality, stability and weigh in on new features? Then please consider donating to my [Patreon](https://www.patreon.com/juliangruber). Not sure how much of my modules you're using? Try [feross/thanks](https://github.com/feross/thanks)!\n\n## License\n\n(MIT)\n\nCopyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "bench/client.js",
    "content": "var multilevel = require('..');\nvar net = require('net');\n\nvar port = process.argv[2];\nvar num = Math.round(Number(process.argv[3]));\nvar str = process.argv[4];\n\nvar write = require('./write')(str);\n\nvar db = multilevel.client()\nvar stream = db.createRpcStream()\nvar con = net.connect(port)\nstream.pipe(con).pipe(stream)\n\nvar start = Date.now()\nwrite(db, num, function (err, results) {\n  console.log(Date.now() - start)\n  con.destroy();\n  process.exit(0);\n})  \n"
  },
  {
    "path": "bench/index.js",
    "content": "/**\n * Results:\n *\n * writing \"1234567890abcdef\" 10000 times\n *\n * native             : 124ms (80645 ops/s)\n * multilevel direct  : 601ms (16639 ops/s)\n * multilevel network : 794ms (12594 ops/s)\n */\n\nvar multilevel = require('..')\nvar levelup = require('levelup')\nvar rimraf = require('rimraf')\nvar net = require('net')\nvar spawn = require('child_process').spawn\n\nvar path = '/tmp/multilevel-test-db'\nvar str = '1234567890abcdef'\nvar clients = 5\n\nvar write = require('./write')(str);\n\nrun(1e2, function () {\n  run(1e3, function () {\n    run(1e4, function () {\n      run(1e5)\n    })\n  })\n})\n\nfunction native (num, cb) {\n  getDb(function (err, db) {\n    if (err) return cb(err) \n    write(db, num, function (err, results) {\n      db.close()\n      cb(err, 'native             : ' + results)\n    })\n  })\n}\n\nfunction fakeNetwork (num, cb) {\n  getDb(function (err, db) {\n    if (err) return cb(err)\n\n    /*var traffic = 0\n    function collect (data) {\n      traffic += data.length\n    }*/\n\n    var dbs = [];\n\n    for (var i = 0; i < clients; i++) {\n      var server = multilevel.server(db)\n      var _db = multilevel.client()\n      var stream = _db.createRpcStream()\n      stream.pipe(server).pipe(stream)\n      dbs.push(_db);\n    }\n\n    /*server.on('data', collect)\n    client.on('data', collect)*/\n\n    setTimeout(function () {\n      write(dbs, num, function (err, results) {\n        db.close();\n        cb(err, 'multilevel direct  : ' + results/* + ', traffic: ' + traffic*/)\n      })  \n    }, 1000)\n  })\n}\n\nfunction realNetwork (num, cb) {\n  getDb(function (err, db) {\n    if (err) return cb(err)\n\n    var server = net.createServer(function (c) {\n      c.pipe(multilevel.server(db)).pipe(c)\n    })\n\n    server.listen(5001, function () {\n      var exited = 0;\n      var duration = 0;\n      for (var i = 0; i < clients; i++) {\n        var start = Date.now();\n        var ps = spawn('node', [__dirname + '/client.js', 5001, num/clients, str]);\n        ps.stderr.pipe(process.stderr)\n        ps.stdout.on('data', function (data) {\n          var _num = Number(data.toString())\n          if (_num > duration) duration = _num\n\n          if (++exited == clients) {\n            server.close();\n            db.close();\n\n            cb(null, 'multilevel network : '\n                      + duration + 'ms ('\n                      + (Math.round(num/duration*1000))\n                      + ' ops/s)')\n          }\n        })\n      }\n    })\n  })\n}\n\nfunction run (num, cb) {\n  console.log('\\nwriting \"%s\" %s times', str, num)\n\n  native(num, function (err, results) {\n    log(err, results)\n    fakeNetwork(num, function (err, results) {\n      log(err, results)\n      realNetwork(num, function (err, results) {\n        log(err, results)\n        if (cb) cb()\n      })\n    })\n  })\n}\n\n\nfunction log (err, results) {\n  if (err) throw err\n  console.log(results)\n}\n\nfunction getDb (cb) {\n  rimraf.sync(path)\n  levelup(path, cb)\n}\n"
  },
  {
    "path": "bench/write.js",
    "content": "module.exports = function (str) {\n  return function write (dbs, num, cb) {\n    if (!Array.isArray(dbs)) dbs = [dbs];\n    var written = 0\n    var start = Date.now()\n\n    function rand () {\n      return dbs[Math.floor(Math.random() * dbs.length)]\n    }\n\n    for (var i = 0; i < num; i++) {\n      rand().put(''+i, str, function (err) {\n        if (err) {\n          var oldCb = cb\n          cb = function () {}\n          return oldCb(err)\n        }\n        if (++written == num) {\n          var duration = Date.now() - start\n          cb(\n            null,\n            duration + 'ms (' + (Math.round(num/duration*1000)) + ' ops/s)'\n          )\n        }\n      })\n    }\n  }\n};\n"
  },
  {
    "path": "example/simple.js",
    "content": "var multilevel = require('..');\nvar level = require('level');\n\nvar DB = level(__dirname + '/.db');\nvar db = multilevel.client();\nvar server = multilevel.server(DB);\nserver.pipe(db.createRpcStream()).pipe(server);\n\ndb.put('foo', 'bar', function (err) {\n  if (err) throw err;\n  db.get('foo', function (err, val) {\n    if (err) throw err;\n    console.log(val);\n  });\n});\n"
  },
  {
    "path": "index.js",
    "content": "var MuxDemux = require('mux-demux/jsonb');\n\nmodule.exports = {\n  client: require('./lib/client')(MuxDemux),\n  server: require('./lib/server')(MuxDemux),\n  writeManifest: require('./lib/write-manifest')\n};\n"
  },
  {
    "path": "lib/client.js",
    "content": "var rpc = require('rpc-stream');\nvar Emitter = require('events').EventEmitter;\nvar duplexer = require('duplexer');\nvar manifest = require('level-manifest');\nvar combine = require('stream-combiner');\nvar inherits = require('util').inherits;\nvar tmpStream = require('tmp-stream');\n\nmodule.exports = function (MuxDemux) {\n\nfunction Db (m) {\n  if (!(this instanceof Db)) return new Db(m);\n  if (!m) m = manifest({ methods: {} });\n  Emitter.call(this);\n\n  this.isClient = true;\n  this._isOpen = false;\n  this.methods = m.methods;\n\n  this.mdm = null;\n  this.client = null;\n  var self = this;\n\n  this._buildAll(m, this, [], null);\n  this.on('pipe', deprecated);\n}\n\ninherits(Db, Emitter);\n\nDb.prototype.sublevel = function (name) {\n  if (!this.sublevels || !this.sublevels[name]) {\n    throw new Error('client cannot create new sublevels');\n  }\n  return this.sublevels[name];\n};\n\nDb.prototype.prefix = function (key) {\n  return this._prefix.slice()\n};\n\nDb.prototype.createRpcStream = function () {\n  var self = this;\n  self._isOpen = true;\n\n  var mdm = self.mdm = MuxDemux({ error: true });\n  mdm.on('end', function () {\n    self._isOpen = false;\n    self.emit('close');\n  });\n\n  var client = self.client = rpc(null, { raw: true });\n  var rpcStream = mdm.createStream('rpc');\n  rpcStream.on('error', function () {});\n  client.pipe(rpcStream).pipe(client);\n\n  setTimeout(function () {\n    self.emit('open');\n  });\n\n  return mdm;\n};\n\nDb.prototype.close = function (cb) {\n  this._isOpen = false;\n  if (this.mdm) this.mdm.end();\n  if (cb) process.nextTick(cb);\n};\n\nDb.prototype.destroy = function () {\n  if (this.mdm) this.mdm.close();\n};\n\nDb.prototype.auth = function () {\n  var args = [].slice.call(arguments);\n  var cb = typeof args[args.length - 1] == 'function'\n    ? args.pop()\n    : function () {};\n  this.client.rpc('auth', args, cb);\n};\n\nDb.prototype.deauth = function () {\n  var args = [].slice.call(arguments);\n  var cb = typeof args[args.length - 1] == 'function'\n    ? args.pop()\n    : function () {};\n  this.client.rpc('deauth', args, cb);\n};\n\n// EventEmitter special casing, to prevent\n// users from listening to db events\n// like \"put\", although they are not supported\n\nvar on = Db.prototype.on;\nvar allowed = [\n  'error',\n  'pipe',\n  'open',\n  'close'\n];\n\nDb.prototype.addEventListener =\nDb.prototype.on = function(ev, fn){\n  if (allowed.indexOf(ev) == -1) throw new Error('not supported');\n  return on.call(this, ev, fn);\n};\n\nDb.prototype.pipe = deprecated;\n\nfunction deprecated () {\n  throw new Error(\n    'The API changed. Use db.createRpcStream().'\n  );\n}\n\n\nDb.prototype._buildAll = function (_db, db, path, parent) {\n  var self = this;\n  var m = manifest(_db);\n\n  for (var k in m.methods) {\n    var method = m.methods[k];\n    var type = method.type;\n    var name = path.concat(k).join('!');\n\n    if (type == 'error') throw new Error(method.message || 'not supported');\n\n    if (/async|sync/.test(type)) {\n      self._asyncSync(db, k, name);\n    } else if (/readable|writable|duplex/.test(type)) {\n      self._stream(db, k, name, type);\n    } else if (type == 'object') {\n      db[k] = new Emitter;\n      self._buildAll(method, db[k], path.concat('.' + k));\n    }\n  }\n\n  db._prefix = path;\n  db._parent = parent;\n\n  for (var name in _db.sublevels) {\n    var sublevel = _db.sublevels[name];\n    db.sublevels = db.sublevels || {};\n    db.sublevels[name] = new Db(sublevel);\n    self._buildAll(sublevel, db.sublevels[name], path.concat(name), db);\n  }\n};\n\nDb.prototype._asyncSync = function (db, k, name) {\n  var self = this;\n\n  db[k] = function () {\n    var args = [].slice.call(arguments);\n    var cb = typeof args[args.length - 1] == 'function'\n      ? args.pop()\n      : null;\n\n    if (/is(Open|Closed)/.test(k) && !cb) {\n      if (k == 'isOpen') return self._isOpen;\n      else return !self._isOpen;\n    }\n\n    if (!cb) cb = function (err) {\n      if (err) db.emit('error', err)\n    };\n\n    self._queue(function () {\n      self.client.rpc(name, args, cb);\n    });\n  };\n};\n\nDb.prototype._stream = function (db, k, name, type) {\n  var self = this;\n\n  db[k] = function () {\n    var args = [].slice.call(arguments);\n    args.unshift(name);\n\n    var tmp = tmpStream();\n\n    self._queue(function () {\n      var mdm = self.mdm;\n      var ts = (\n          type === 'readable'\n        ? mdm.createReadStream(args)\n        : type == 'writable'\n        ? mdm.createWriteStream(args)\n        : type == 'duplex'\n        ? mdm.createStream(args)\n        : (function () { throw new Error('not supported') })()\n      );\n      ts.autoDestroy = false;\n      tmp.replace(ts);\n    });\n\n    return tmp;\n  };\n};\n\nDb.prototype._queue = function (fn) {\n  if (this._isOpen) fn();\n  else this.once('open', fn);\n};\n\nreturn Db;\n\n};\n\n"
  },
  {
    "path": "lib/server.js",
    "content": "var rpc = require('rpc-stream');\nvar manifest = require('level-manifest');\n\nmodule.exports = function (MuxDemux) {\n\nreturn function (db, opts) {\n  if (typeof db == 'string') throw new Error('database instance required');\n\n  if('function' === typeof db.sublevel) {\n    if(!(db.version >= '6'))\n      throw new Error('expected a level-sublevel@6 or greater')\n  }\n\n  var mdm = MuxDemux({ error: true });\n\n  opts = opts || {};\n\n  var deauth = opts.deauth || function () {};\n  var auth = opts.auth || function () {\n    var cb = [].pop.call(arguments);\n    cb(null, true);\n  };\n  var access = opts.access || function () { return true };\n\n  var server = rpc(null, { raw: true, flattenError: flatten });\n  var handlers = {};\n\n  (function buildAll (db, path) {\n    var m = manifest(db);\n    for (var k in m.methods) (function (k) {\n      var name = path.concat(k).join('!');\n      var method = m.methods[k];\n\n      if (method.type == 'async') {\n        server.createLocalCall(name, function (args, cb) {\n          access(server.sessionData, db, k, args);\n          args.push(cb);\n          db[k].apply(db, args);\n        });\n      } else if (method.type == 'sync') {\n        server.createLocalCall(name, function (args, cb) {\n          access(server.sessionData, db, k, args);\n          var r;\n          try { r = db[k].apply(db, args) }\n          catch (err) { return cb(err) }\n          cb(null, r);\n        });\n      } else if (method.type == 'object') {\n        db[k].methods = method.methods;\n        buildAll(db[k], path.concat('.' + k));\n      } else {\n        handlers[name] = function (args) {\n          access(server.sessionData, db, k, args);\n          return db[k].apply(db, args);\n        };\n      }\n    })(k);\n\n    for(var name in db.sublevels) {\n      buildAll(db.sublevels[name], path.concat(name));\n    }\n  })(db, []);\n\n  server.createLocalCall('auth', function (args, cb) {\n    auth.apply(null, args.concat(function authCb (err, data) {\n      if (err) return cb(err);\n      server.sessionData = data;\n      cb(null, data);\n    }));\n  });\n\n  server.createLocalCall('deauth', function (args, cb) {\n    server.sessionData = null;\n    if (opts.deauth) opts.deauth.apply(null, args);\n    else cb();\n  });\n\n  mdm.on('connection', function (con) {\n    con.on('error', function () {});\n\n    if (con.meta == 'rpc') return con.pipe(server).pipe(con);\n\n    try {\n      var stream = handlers[con.meta[0]](con.meta.slice(1));\n      // prevent iterators from staying open when connection fails\n      con.once('error', function () {\n        var method = stream[stream.readable ? 'destroy' : 'end']\n        if(method) method.call(stream)\n      });\n      if (stream.readable) stream.pipe(con);\n      if (stream.writable) con.pipe(stream);\n      stream.on('error', function (err) {\n        con.error(flatten(err));\n      });\n    } catch (err) {\n      con.error(flatten(err));\n    }\n  });\n\n  return mdm;\n};\n\n};\n\nfunction flatten(err){\n  if(!(err instanceof Error)) return err;\n  var err2 = {\n    message: err.message,\n    type: err.type,\n    notFound: err.notFound,\n    status: err.status\n  };\n  for (var k in err) err2[k] = err[k];\n  return err2;\n}\n"
  },
  {
    "path": "lib/write-manifest.js",
    "content": "var fs = require('fs');\nvar createManifest = require('level-manifest');\n\nmodule.exports = writeManifest;\n\nfunction writeManifest (db, path) {\n  var manifest = createManifest(db);\n  fs.writeFileSync(path, JSON.stringify(manifest, null, 2));\n  return manifest;\n}\n"
  },
  {
    "path": "msgpack.js",
    "content": "var MuxDemux = require('mux-demux/msgpack');\n\nmodule.exports = {\n  client: require('./lib/client')(MuxDemux),\n  server: require('./lib/server')(MuxDemux),\n  writeManifest: require('./lib/write-manifest')\n};\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"multilevel\",\n  \"version\": \"7.2.3\",\n  \"description\": \"Expose a leveldb over the network.\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"make test\",\n    \"test-browser\": \"make test-browser\"\n  },\n  \"repository\": \"git://github.com/juliangruber/multilevel\",\n  \"keywords\": [\n    \"levelup\",\n    \"leveldb\",\n    \"rpc\",\n    \"stream\",\n    \"server\",\n    \"client\"\n  ],\n  \"author\": \"Julian Gruber <julian@juliangruber.com>\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"duplexer\": \"^0.1.1\",\n    \"level-manifest\": \"^1.2.0\",\n    \"mux-demux\": \"^3.7.9\",\n    \"rpc-stream\": \"^2.1.2\",\n    \"stream-combiner\": \"^0.2.2\",\n    \"tmp-stream\": \"^0.3.2\"\n  },\n  \"devDependencies\": {\n    \"bops\": \"^1.0.0\",\n    \"level-live-stream\": \"^1.4.11\",\n    \"level-sublevel\": \"^6.5.2\",\n    \"level-ws\": \"0.0.1\",\n    \"memdb\": \"^1.3.1\",\n    \"tape\": \"^4.2.2\",\n    \"through\": \"^2.3.8\"\n  },\n  \"engines\": {\n    \"node\": \">0.6\"\n  },\n  \"testling\": {\n    \"files\": \"test/*.js\",\n    \"browsers\": [\n      \"ie/8..latest\",\n      \"firefox/17..latest\",\n      \"firefox/nightly\",\n      \"chrome/22..latest\",\n      \"chrome/canary\",\n      \"opera/12..latest\",\n      \"opera/next\",\n      \"safari/5.1..latest\",\n      \"ipad/6.0..latest\",\n      \"iphone/6.0..latest\",\n      \"android-browser/4.2..latest\"\n    ]\n  }\n}\n"
  },
  {
    "path": "test/access.js",
    "content": "require('./util')(function (test, multilevel, getDb) {\n\n  test('access error', function (t) {\n    t.plan(2);\n\n    var multilevel = require('..');\n    var level = require('memdb');\n\n    var db = level('db');\n\n    var server = multilevel.server(db, {\n      access: function () {\n        throw new Error('unauthorized');\n      }\n    });\n\n    var db = multilevel.client();\n    server.pipe(db.createRpcStream()).pipe(server);\n\n    db.createReadStream()\n      .on('error', function (err) {\n        t.ok(err);\n        t.equal(err.message, 'unauthorized');\n      });\n  });\n\n});\n\n"
  },
  {
    "path": "test/async-emit-error.js",
    "content": "require('./util')(function (test, _, getDb) {\n\n  test('async emits error', function (t) {\n    t.plan(2);\n  \n    getDb(function (db, dispose) {\n      db.get('foo');\n      db.on('error', function (err) {\n        t.ok(err);\n        t.equal(err.type, 'NotFoundError');\n        dispose();\n      });\n    });\n  });\n\n});\n"
  },
  {
    "path": "test/async.js",
    "content": "var getDb = require('./util').getDb\nvar test = require('tape');\n\nrequire('./util')(function (test, _, getDb) {\n\n  test('async', function (t) {\n    t.plan(1)\n  \n    getDb(function (db, dispose) {\n      db.put('foo', 'bar', function (err) {\n        if (err) throw err\n        db.get('foo', function (err, value) {\n          if (err) throw err\n          t.equal(value, 'bar')\n          dispose()\n        })\n      })\n    })\n  })\n  \n  test('async error', function (t) {\n    t.plan(3)\n  \n    getDb(function (db, dispose) {\n      db.get('foo', function (err) {\n        t.ok(err)\n        t.ok(err.notFound)\n        t.equal(err.type, 'NotFoundError')\n      })\n    })\n  })\n\n})\n"
  },
  {
    "path": "test/auth.js",
    "content": "require('./util')(function (test, multilevel, getDb) {\n\n  var sublevel = require('level-sublevel');\n\n  var uname = 'user_' + Math.random();\n  var pword = 'pw_' + Math.random();\n  var opts = {\n    auth: function (username, password, cb) {\n      if (username == uname && password == pword) {\n        cb(null, {name: uname});\n      } else {\n        cb(new Error('not authorized'));\n      }\n    },\n    access: function (user, db, name, args) {\n      if (!user && ~[\n        'put', 'batch', 'del',\n        'createWriteStream',\n        'writeStream'\n        ].indexOf(name)) {\n        throw new Error('auth() to write');\n      }\n    }\n  };\n\n  test('auth', function (t) {\n    t.plan(8);\n    \n    getDb(function (db) {\n      db = sublevel(db);\n      db.sublevel('foo');\n      t.notOk(db.isClient);\n      return {\n        opts: opts,\n        db: db\n      };\n    }, \n    function (db, dispose) {\n      t.ok(db.isClient);\n\n      db.put('foo', 'not allowed', function (err) {\n        t.ok(err);\n\n        db.auth(uname, pword, function (err, user) {\n          t.notOk(err);\n          t.equal(uname, user.name);\n\n          db.put('foo', 'bar', function (err) {\n            t.error(err);\n\n            db.get('foo', function (err, value) {\n              t.error(err);\n              t.equal(value, 'bar');\n              dispose();\n            });\n          });\n        });\n      });\n    });\n  });\n\n  test('auth - nested', function (t) {\n    t.plan(7);\n    \n    getDb(function (db) {\n      db = sublevel(db);\n      db.sublevel('foo');\n      t.notOk(db.isClient);\n      return {\n        opts: opts,\n        db: db\n      };\n    }, \n    function (db, dispose) {\n      t.ok(db.isClient);\n      var fooDb = db.sublevel('foo');\n      \n      fooDb.put('foo', 'not allowed', function (err) {\n        t.ok(err, 'not authed');\n\n        db.auth(uname, pword, function (err) {\n          t.notOk(err, 'is authed');\n\n          fooDb.put('foo', 'bar', function (err) {\n            t.error(err);\n\n            fooDb.get('foo', function (err, value) {\n              t.error(err);\n              t.equal(value, 'bar');\n              dispose();\n            });\n          });\n        });\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "test/binary.js",
    "content": "var getDb = require('./util').getDb;\nvar test = require('tape');\nvar binary = require('bops');\n\nrequire('./util')(function (test, _, getDb) {\n\n  test('binary', function (t) {\n    var opts = { valueEncoding : 'binary' };\n    getDb(function (db, dispose) {\n      db.put('foo', binary.from([1,2,3]), opts, function (err) {\n        t.error(err);\n        db.get('foo', opts, function (err, value) {\n          t.error(err);\n          t.ok(binary.is(value));\n          t.equal(binary.to(value), binary.to(binary.from([1,2,3])));\n          dispose();\n          t.end();\n        });\n      });\n    });\n  });\n\n})\n"
  },
  {
    "path": "test/disabled/events.js",
    "content": "var getDb = require('./util').getDb\nvar test = require('tap').test\n\ntest('events', function (t) {\n  t.plan(2)\n  \n  getDb(function (db, dispose) {\n    db.on('put', function (key, value) {\n      t.equal(key, 'foo')\n      t.equal(value, 'bar')\n      dispose()\n    })\n\n    db.put('foo', 'bar')\n  })\n})\n"
  },
  {
    "path": "test/disconnect.js",
    "content": "var getLocalDb = require('./util').getLocalDb;\nvar through = require('through');\nvar multilevel = require('..');\nvar test = require('tape');\n\ntest('disconnect', function (t) {\n  t.plan(4);\n\n  var db = getLocalDb();\n  var server = multilevel.server(db);\n  var client = multilevel.client();\n  var fakeConnection = through();\n  var readStream = db.createReadStream;\n  var stream;\n  var chunks = 0;\n\n  // get a reference to the server read stream\n  db.createReadStream = function () {\n    stream = readStream.apply(this, arguments);\n    stream.on('data', function () { chunks++ });\n    return stream\n  };\n\n  setTimeout(function () {\n    server.pipe(fakeConnection).pipe(client.createRpcStream()).pipe(server);\n    server.on('error',function(){\n      t.fail('server emitted error');\n    });\n  }, 10);\n\n  client.batch([\n    { type: 'put', key: 'a', value: \"1\" },\n    { type: 'put', key: 'b', value: \"2\" },\n    { type: 'put', key: 'c', value: \"3\" }\n  ], function (err) {\n    t.error(err, 'batch written');\n\n    var errored = false;\n    client.createReadStream()\n      .on('data',function(data){\n        t.equals(data.value, '1', 'data received');\n        fakeConnection.destroy();\n      })\n      .on('error',function (error) {\n        errored = true;\n        var hasDisconnect = error.message.indexOf('disconnect') > -1;\n        t.ok(hasDisconnect, 'emitted disconnect error');\n      });\n\n    stream.on('close', function () {\n      t.equals(chunks, 1, 'database read stream closed');\n    });\n  });\n\n});\n"
  },
  {
    "path": "test/duplex.js",
    "content": "var sublevel = require('level-sublevel')\nvar MuxDemux = require('mux-demux')\n\nrequire('./util')(function (test, _, getDb) {\n\n  test('duplex stream exposed', function (t) {\n    t.plan(1)\n  \n    getDb(function (db, dispose) {\n      var db = sublevel(db)\n      var bar = db.sublevel('bar')\n\n      // add method so it's included in the manifest\n      bar.methods['dup'] = {type: 'duplex'}\n\n      bar.dup = MuxDemux().createStream\n\n      return { db: db }\n    },\n    function (db, dispose) {\n      var bar = db.sublevels['bar']\n      var dStream = bar.dup()\n      t.ok(dStream.write({ key : 'bar', value : 'baz' }));\n    })\n  })\n})\n"
  },
  {
    "path": "test/event.js",
    "content": "\nvar getDb = require('./util').getDb\nvar test = require('tape');\n\nrequire('./util')(function (test, _, getDb) {\n\n  test('event', function (t) {\n    t.plan(1)\n  \n    getDb(function (db, dispose) {\n      t.throws(function(){\n        db.on('put', function(){});\n      })\n    })\n  })\n\n})\n"
  },
  {
    "path": "test/functionInObject.js",
    "content": "var getDb = require('./util').getDb;\nvar test = require('tape');\n\nrequire('./util')(function (test, _, getDb) {\n\n  var obj = {\n    getImage: function () {},\n    a: 2\n  };\n\n  test('function in json', function (t) {\n    t.plan(3);\n  \n    getDb(function (db, dispose) {\n      db.put('foo', obj, { valueEncoding: 'json' }, function (err) {\n        t.error(err);\n        db.get('foo', { valueEncoding: 'json' }, function (err, val) {\n          t.error(err);\n          t.equal(val.a, 2);\n          dispose();\n        });\n      });\n    });\n  });\n\n});\n"
  },
  {
    "path": "test/isOpenClosed.js",
    "content": "require('./util')(function (test, _, getDb) {\n\n  test('sync isOpen / isClosed with sync close', function (t) {\n    t.plan(4);\n\n    getDb(function (db, dispose) {\n      t.ok(db.isOpen());\n      t.notOk(db.isClosed());\n\n      db.close();\n\n      t.notOk(db.isOpen());\n      t.ok(db.isClosed());\n\n      dispose();\n    });\n  });\n\n  test('sync isOpen / isClosed with async close', function (t) {\n    t.plan(5);\n\n    getDb(function (db, dispose) {\n      t.ok(db.isOpen());\n      t.notOk(db.isClosed());\n\n      db.close(function(err) {\n        t.error(err);\n\n        t.notOk(db.isOpen());\n        t.ok(db.isClosed());\n\n        dispose();\n      });\n    });\n  });\n\n});\n"
  },
  {
    "path": "test/live-stream.js",
    "content": "require('./util')(function (test, _, getDb) {\n\n  var sublevel = require('level-sublevel');\n  var LiveStream = require('level-live-stream');\n\n  test('stream', function (t) {\n    t.plan(20);\n    var j = 10;\n\n    getDb(function (db) {\n      db = sublevel(db);\n      LiveStream.install(db.sublevel('foo'));\n      return { db: db };\n    },\n    function (db, dispose) {\n      var foo = db.sublevel('foo');\n      var ls = foo.liveStream();\n      ls.on('data', function (d) {\n        t.equal(j-- * 1000, Number(d.value));\n\n        if (j) return;\n\n        ls.destroy();\n        dispose();\n      });\n      ls.on('error', function () {});\n\n      setTimeout(function() {\n        var i = 10;\n        var id = setInterval(function () {\n          foo.put(i, i*1000, function (err) {\n            t.error(err);\n          });\n          if (--i) return;\n          clearInterval(id);\n        }, 0);\n      }, 10);\n    });\n  });\n});\n\n"
  },
  {
    "path": "test/nested-async.js",
    "content": "\nvar sublevel = require('level-sublevel')\n\nrequire('./util')(function (test, _, getDb) {\n  test('async', function (t) {\n    t.plan(3)\n  \n    getDb(function (db) {\n      db = sublevel(db)\n      db.sublevel('foo')\n      t.notOk(db.isClient)\n      return { db: db }\n    }, \n    function (db, dispose) {\n      t.ok(db.isClient)\n      db.sublevels['foo'].put('foo', 'bar', function (err) {\n        if (err) throw err\n        db.sublevels['foo'].get('foo', function (err, value) {\n          if (err) throw err\n          t.equal(value, 'bar')\n          dispose()\n        })\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "test/nested-batch.js",
    "content": "var getDb = require('./util').getDb\nvar test = require('tape')\nvar sublevel = require('level-sublevel')\n\nrequire('./util')(function (test, _, getDb) {\n\n  test('async', function (t) {\n    t.plan(2)\n\n    getDb(function (db) {\n      db = sublevel(db)\n      db.sublevel('foo')\n      db.sublevel('bar')\n      return { db: db }\n    }, \n    function (db, dispose) {\n      db.sublevel('foo').batch([\n        {key:'f', value:'1', type: 'put'},\n        {key:'b', value:'2', type: 'put', prefix: db.sublevel('bar').prefix()}\n      ],\n      function (err) {\n        if (err) throw err\n        db.sublevel('foo').get('f', function (err, value) {\n          if (err) throw err\n          t.equal(value, '1')\n          db.sublevel('bar').get('b', function (err, value) {\n            if (err) throw err\n            t.equal(value, '2')\n            dispose()\n          })\n        })\n      })\n    })\n  })\n\n})\n"
  },
  {
    "path": "test/nested-stream.js",
    "content": "var getDb = require('./util').getDb\nvar test = require('tape')\nvar sublevel = require('level-sublevel')\n\nrequire('./util')(function (test, _, getDb) {\n\n  test('nested-stream', function (t) {\n    t.plan(4)\n\n    getDb(function (db) {\n      db = sublevel(db)\n      db.sublevel('foo')\n      return { db: db }\n    },\n    function (db, dispose) {\n      db = db.sublevels['foo'];\n      db.put('foo', 'bar', function (err) {\n        if (err) throw err\n        db.createReadStream()\n        .on('data', function (data) {\n          t.equal(data.key, 'foo')\n          t.equal(data.value, 'bar')\n        })\n        .on('end', function () {\n          db.batch([\n            { key : 'bar', value : 'baz' }\n          ], function (err) {\n            if(err) throw err\n            // temporary fix for level-js\n            setTimeout(function () {\n              db.get('bar', function (err, value) {\n                t.notOk(err);\n                t.equal(value, 'baz');\n                dispose();\n              });\n            }, 100);\n          })\n        })\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "test/nested.js",
    "content": "require('./util')(function (test, _, getDb) {\n\n  var Emitter = require('events').EventEmitter;\n\n  test('nested', function (t) {\n    t.plan(10);\n\n    getDb(function (db) {\n      db.nested = {\n        get: function(cb) { cb(null, 'hola') },\n        deeper: {\n          get: function(cb) { cb(null, 'ola') }\n        }\n      };\n      db.methods = {\n        nested: {\n          type: 'object',\n          methods: {\n            get: { type: 'async' },\n            deeper: {\n              type: 'object',\n              methods: {\n                get: { type: 'async' }\n              }\n            }\n          }\n        }\n      };\n      return { db: db };\n    },\n    function (db, dispose) {\n      t.ok(db.nested, 'has nested');\n      t.ok(db.nested instanceof Emitter, 'nested is emitter');\n      t.ok(db.nested.get, 'has nested.get');\n      t.ok(db.nested.deeper, 'has nested.deeper');\n      t.ok(db.nested.deeper instanceof Emitter, 'nested.deeper is emitter');\n      t.ok(db.nested.deeper.get, 'has nested.deeper.get');\n      \n      db.nested.get(function(err, value) {\n        t.error(err, 'nested.get without error');\n        t.equal(value, 'hola', 'nested.get has value');\n        \n        db.nested.deeper.get(function(err, value) {\n          t.error(err, 'nested.deeper.get without error');\n          t.equal(value, 'ola', 'nested.deeper.get has value');\n        });\n      });\n    });\n  });\n});\n\n"
  },
  {
    "path": "test/node/manifest.js",
    "content": "var test = require('tape');\nvar writeManifest = require('../..').writeManifest;\nvar MemDB = require('memdb');\n\ntest('write manifest', function (t) {\n  var db = MemDB();\n  var result = writeManifest(db, __dirname + '/manifest.json');\n  var manifest = require('./manifest.json');\n  t.ok(manifest);\n  t.deepEqual(result, manifest);\n  t.end();\n});\n"
  },
  {
    "path": "test/pipe.js",
    "content": "var Stream = require('stream');\n\nrequire('./util')(function (test, _, getDb) {\n\n  test('pipe', function (t) {\n    t.plan(2);\n  \n    getDb(function (db, dispose) {\n      t.throws(function () {\n        db.pipe();\n      });\n      t.throws(function () {\n        (new Stream()).pipe(db);\n      });\n      dispose();\n    });\n  });\n});\n"
  },
  {
    "path": "test/plugin.js",
    "content": "var sublevel = require('level-sublevel')\n\nrequire('./util')(function (test, _, getDb) {\n\n  test('stream', function (t) {\n    t.plan(2)\n  \n    getDb(function (db) {\n      db = sublevel(db)\n      var foo = db.sublevel('foo')\n\n      //add inc to the manifest\n      foo.methods['inc'] = {type: 'async'}\n\n      //implement it\n      foo.inc = function (f, cb) {\n        if(!cb) {\n          cb = f\n          foo.get('inc', function (err, val) {\n            cb(err, val)\n          })\n        } else {\n          foo.get('inc', function (err, val) {\n            val = Number(val || 0) + Number(f)\n            foo.put('inc', val, function (err) {\n              if(err) cb(err)\n              else    cb(null, val)\n            })\n          })\n        }\n      }\n\n      return { db: db }\n    },\n    function (db, dispose) {\n      var foo = db.sublevels['foo']\n      foo.inc(1, function (err, val) {\n        t.equal(val, 1)\n        foo.inc(2, function (err, val) {\n          t.equal(val, 3)\n          t.end()\n          dispose()\n        })\n      })\n    })\n  })\n\n})\n"
  },
  {
    "path": "test/reconnect.js",
    "content": "var multitest = require('./util')\nvar getLocalDb = multitest.getLocalDb\n\nmultitest(function (test, multilevel) {\n\n  test('reconnect', function (t) {\n    t.plan(3);\n\n    var db = getLocalDb();\n    var server = multilevel.server(db);\n    var client = multilevel.client();\n\n    setTimeout(function () {\n      var rpc = client.createRpcStream();\n      server.pipe(client.createRpcStream()).pipe(server);\n    }, 10);\n\n    client.put('foo', 'bar', function (err) {\n      t.error(err);\n      client.get('foo', function (err, val) {\n        t.error(err);\n        t.equals(val, 'bar');\n        db.close();\n      });\n    });\n  });\n\n});\n"
  },
  {
    "path": "test/stream-error.js",
    "content": "var multilevel = require('..');\nvar through = require('through');\nvar MemDB = require('memdb');\n\nrequire('./util')(function (test) {\n\n  test('stream error', function (t) {\n    var db = {};\n    db.createReadStream = function(){\n      var stream = through();\n      process.nextTick(function(){\n        stream.emit('error', new Error('oops'));\n      });\n      return stream;\n    };\n\n    var server = multilevel.server(db);\n    var client = multilevel.client();\n    server.pipe(client.createRpcStream()).pipe(server);\n\n    var stream = client.createReadStream();\n    stream.on('error', function(err){\n      t.equal(err.message, 'oops');\n      t.end();\n    });\n  });\n});\n\n"
  },
  {
    "path": "test/stream.js",
    "content": "var levelws = require('level-ws');\n\nrequire('./util')(function (test, _, getDb) {\n\n  test('stream', function (t) {\n    t.plan(5);\n\n    getDb(function (db, dispose) {\n      levelws(db);\n\n      db.put('foo', 'bar', function (err) {\n        t.error(err);\n\n        db.readStream()\n        .on('data', function (data) {\n          t.equal(data.key, 'foo');\n          t.equal(data.value, 'bar');\n        })\n        .on('end', function () {\n          var stream = db.writeStream();\n          stream.write({ key : 'bar', value : 'baz' });\n          stream.on('close', function () {\n            // temporary fix for level-js\n            setTimeout(function () {\n              db.get('bar', function (err, value) {\n                t.notOk(err);\n                t.equal(value, 'baz');\n                dispose();\n              });\n            }, 100);\n          });\n          stream.end();\n        })\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "test/sync.js",
    "content": "require('./util')(function (test, _, getDb) {\n\n  test('sync', function (t) {\n    t.plan(1)\n  \n    getDb(function (db, dispose) {\n      db.isClosed(function (err, isClosed) {\n        t.equal(isClosed, false)\n        dispose()\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "test/util.js",
    "content": "var MemDB = require('memdb');\nvar manifest = require('level-manifest');\nvar tape = require('tape');\nvar multilevel = require('..');\nvar multilevelMsgpack = require('../msgpack');\n\nvar DEBUG = process.env.DEBUG;\n  \nvar util = module.exports = function (tests) {\n  function prefix(pre) {\n    return function (name, test) {\n      return tape(pre + ': ' + name, test);\n    };\n  }\n\n  tests(\n    prefix('jsonb'),\n    multilevel,\n    util.createGetDb(multilevel)\n  );\n  tests(\n    prefix('msgpack'),\n    multilevelMsgpack,\n    util.createGetDb(multilevelMsgpack)\n  );\n};\n\nutil.getLocalDb = MemDB;\n\nutil.createGetDb = function (multilevel) {\n  return function (setup, cb) {\n    if (!cb) {\n      cb = setup;\n      setup = null;\n    }\n\n    var db = util.getLocalDb();\n    var opts;\n    if (setup) {\n      var ret = setup(db);\n      opts = ret.opts;\n      db = ret.db;\n    }\n\n    var m = manifest(db);\n\n    var server = multilevel.server(db, opts);\n    server.on('data', function (data) {\n      DEBUG && console.log('S -> ' + data.toString());\n    });\n    var _db = multilevel.client(m);\n\n    function createRpcStream () {\n      var rpcStream = _db.createRpcStream();\n      rpcStream.on('data', function (data) {\n        DEBUG && console.log('S <- ' + data.toString());\n      });\n      return rpcStream;\n    }\n\n    server.pipe(createRpcStream()).pipe(server);\n    cb(_db, dispose);\n\n    function dispose () {\n      db.close();\n    }\n  };\n};\n\nutil.getDb = util.createGetDb(multilevel);\n"
  }
]