Nuno Job
Geek. Open-source enthusiast. Shaping the future of the node.js ☁ @nodejitsu. Founder @thenodefirm& curator @lxjs
This is the old blog, check the new one at nunojob.com

Nano 3

Nano is a dead simple, minimalistic couchdb client for node.js.

we just released version three, and this post outlines so important changes.

Pool size & Cookies

One of the things the users where worried the most was about the lack of support for authentication and setting the pool size. As for authentication, it normally ends up being unnecessary and based on miss conceptions by users on how couchdb works.

As for the pool size, well that's another story.

In node.js your pool size determines the maximum number of parallel active connections you can run, while others get queued. The default is 5 (reference needed) and for some applications changing this is an important feature of a CouchDB client.

Nano now support a new object literal in the configuration called request_defaults that will help you doing this. You should follow the request documentation for details, as they are beyond the scope of nano.

  var db = require('nano')(
    { "url"             : "http://localhost:5984/foo"
    , "request_options" : { "proxy" : "http://someproxy" }
    , "log"             : function (id, args) { 
        console.log(id, args);
      }
    });

Follow

If you love follow and you are tired of requiring both nano and follow this is your release. You can now use db.follow just like you use follow:

  var feed = db.follow({since: "now"});
  feed.on('change', function (change) {
    console.log("change: ", change);
  });
  feed.follow();
  process.nextTick(function () {
    db.insert({"bar": "baz"}, "bar");
  });

Callback style is also supported.

Atomic

We have updateWithHandler since nano@2.x.x. However this method was renamed to atomic. Another api change is that the document is now sent over using body, instead of the query string. This fixes the limitation many of our production users had performing atomic updates with very large documents:

  db.atomic("update", "inplace", "foobar", 
  {field: "foo", value: "bar"}, function (error, response) {
    assert.equal(error, undefined, "Failed to update");
    assert.equal(response.foo, "bar", "Update worked");
  });

A fully functioning example is on the test suite. Same as for other methods really, the tests are an excellent source of working samples.

Streaming bug fixes

There was a problem when streaming non attachments from CouchDB in nano@2.1.0. This was fixed in both nano@2.1.1 and nano@3.0.0.

New tests

Testing http apis is hard. I think I finally cracked a way that is both easy to ready (and where tests also work as live examples) while not having a lot of clutter related to HTTP mocking:

  var specify  = require('specify')
    , helpers  = require('../helpers')
    , timeout  = helpers.timeout
    , nano     = helpers.nano
    , nock     = helpers.nock
    ;

  var mock = nock(helpers.couch, "att/insert")
    , db = nano.use("att_insert")
    ;

  specify("att_insert:setup", timeout, function (assert) {
    nano.db.create("att_insert", function (err) {
      assert.equal(err, undefined, "Failed to create database");
    });
  });

  specify("att_insert:test", timeout, function (assert) {
    db.attachment.insert("new", "att", "Hello World!", "text/plain",
      function (error, att) {
        assert.equal(error, undefined, "Should store the attachment");
        assert.equal(att.ok, true, "Response should be ok");
        assert.ok(att.rev, "Should have a revision number");
    });
  });

  specify("att_insert:teardown", timeout, function (assert) {
    nano.db.destroy("att_insert", function (err) {
      assert.equal(err, undefined, "Failed to destroy database");
      assert.ok(mock.isDone(), "Some mocks didn't run");
    });
  });

  specify.run(process.argv.slice(2));

Mocks are now on fixtures and they look like this:

  [
    { "method"   : "put"
    , "path"     : "/att_insert"
    , "status"   : 201
    , "response" : "{ \"ok\": true }" 
    }
  , { "method"   : "put"
    , "path"     : "/att_insert/new/att"
    , "body"     : "\"Hello World!\""
    , "status"   : 201
    , "response" : "{\"ok\": true, \"id\": \"new\", \"rev\": \"1-921bd51\" }"
    }
  , { "method"   : "delete"
    , "path"     : "/att_insert"
    , "status"   : 200
    , "response" : "{ \"ok\": true }" 
    }
  ]