Merge pull request #303 from shtaft/patch-2
Update README.md
diff --git a/.travis.yml b/.travis.yml
index 7de7b97..c0f8448 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,10 +11,11 @@
- "0.11"
- "0.12"
- "iojs"
+ - "4.2"
+ - "node"
services:
- couchdb
os:
- linux
- - osx
before_install:
- npm update -g npm
diff --git a/README.md b/README.md
index a51d6f7..d2ebc3a 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,7 @@
- [nano.db.replicate(source, target, [opts], [callback])](#nanodbreplicatesource-target-opts-callback)
- [nano.db.changes(name, [params], [callback])](#nanodbchangesname-params-callback)
- [nano.db.follow(name, [params], [callback])](#nanodbfollowname-params-callback)
+ - [nano.db.info([callback])](#nanodbinfocallback)
- [nano.use(name)](#nanousename)
- [nano.request(opts, [callback])](#nanorequestopts-callback)
- [nano.config](#nanoconfig)
@@ -300,6 +301,16 @@
});
```
+### nano.db.info([callback])
+
+gets database information.
+
+nano.db.info(function(err, body) {
+ if (!err) {
+ console.log('got database info'', body);
+ }
+});
+
### nano.use(name)
creates a scope where you operate inside `name`.
@@ -411,7 +422,7 @@
The `insert` function can also be used with the method signature `db.insert(doc,[callback])`, where the `doc` contains the `_id` field e.g.
~~~ js
-var alice = cloudant.use('alice')
+var alice = nano.use('alice')
alice.insert({ _id: 'myid', crazy: true }, function(err, body) {
if (!err)
console.log(body)
@@ -421,7 +432,7 @@
and also used to update an existing document, by including the `_rev` token in the document being saved:
~~~ js
-var alice = cloudant.use('alice')
+var alice = nano.use('alice')
alice.insert({ _id: 'myid', _rev: '1-23202479633c2b380f79507a776743d5', crazy: false }, function(err, body) {
if (!err)
console.log(body)
@@ -482,10 +493,10 @@
### db.list([params], [callback])
-list all the docs in the database with optional query string additions `params`.
+list all the docs in the database with optional query string additions `params`. This is useful for searching.
``` js
-alice.list(function(err, body) {
+alice.list({startkey:'cat', limit:3}, function(err, body) {
if (!err) {
body.rows.forEach(function(doc) {
console.log(doc);
@@ -493,6 +504,7 @@
}
});
```
+For a full list of params, see [couchdb doc](https://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options).
### db.fetch(docnames, [params], [callback])
diff --git a/examples/express.js b/examples/express.js
index 51dceac..b49ba1d 100644
--- a/examples/express.js
+++ b/examples/express.js
@@ -12,16 +12,19 @@
var express = require('express')
, db = require('nano')('http://localhost:5984/my_couch')
- , app = module.exports = express.createServer()
+ , app = module.exports = express()
;
-app.get('/', function(request,response) {
- db.get('foo', function (error, body, headers) {
- if(error) { return response.send(error.message, error['status-code']); }
- response.send(body, 200);
- });
- });
+app.get('/', function(req, res) {
+ db.get('foo', function (error, body, headers) {
+ if(error) {
+ res.status(error.statusCode);
+ return res.send(error.message);
+ }
+ res.status(200);
+ res.send(body);
+ });
});
app.listen(3333);
-console.log('server is running. check expressjs.org for more cool tricks');
+console.log('server is running. check expressjs.com for more cool tricks');
diff --git a/lib/nano.js b/lib/nano.js
index ab97228..81d12d7 100644
--- a/lib/nano.js
+++ b/lib/nano.js
@@ -61,6 +61,13 @@
}
}
+ function scrub(str) {
+ if (str) {
+ str = str.replace(/\/\/(.*)@/,"//XXXXXX:XXXXXX@");
+ }
+ return str;
+ }
+
function relax(opts, callback) {
if (typeof opts === 'function') {
callback = opts;
@@ -224,6 +231,13 @@
// fix cloudant issues where they give an erlang stacktrace as js
delete parsed.stack;
+ // scrub credentials
+ req.uri = scrub(req.uri);
+ rh.uri = scrub(rh.uri);
+ if (req.headers.cookie) {
+ req.headers.cookie = "XXXXXXX";
+ }
+
callback(errs.merge({
message: 'couch returned ' + rh.statusCode,
scope: 'couch',
@@ -379,12 +393,18 @@
// http://docs.couchdb.org/en/latest/api/document/common.html#delete--db-docid
function destroyDoc(docName, rev, callback) {
- return relax({
- db: dbName,
- doc: docName,
- method: 'DELETE',
- qs: {rev: rev}
- }, callback);
+ if(!docName) {
+ if(callback)
+ callback("Invalid doc id", null);
+ }
+ else {
+ return relax({
+ db: dbName,
+ doc: docName,
+ method: 'DELETE',
+ qs: {rev: rev}
+ }, callback);
+ }
}
// http://docs.couchdb.org/en/latest/api/document/common.html#get--db-docid
@@ -452,6 +472,7 @@
qs = {};
}
+ qs = qs || {};
qs['include_docs'] = true;
return relax({
@@ -485,6 +506,15 @@
var viewPath = '_design/' + ddoc + '/_' + meta.type + '/' + viewName;
+ // Several search parameters must be JSON-encoded; but since this is an
+ // object API, several parameters need JSON endoding.
+ var paramsToEncode = ['counts', 'drilldown', 'group_sort', 'ranges', 'sort'];
+ paramsToEncode.forEach(function(param) {
+ if (param in qs) {
+ qs[param] = JSON.stringify(qs[param]);
+ }
+ });
+
if (qs && qs.keys) {
var body = {keys: qs.keys};
delete qs.keys;
@@ -533,6 +563,10 @@
// http://docs.couchdb.org/en/latest/api/ddoc/render.html#put--db-_design-ddoc-_update-func-docid
function updateWithHandler(ddoc, viewName, docName, body, callback) {
+ if (typeof body === 'function') {
+ callback = body;
+ body = undefined;
+ }
return view(ddoc, viewName + '/' + encodeURIComponent(docName), {
type: 'update',
method: 'PUT',
diff --git a/package.json b/package.json
index 6ee064b..7517baf 100644
--- a/package.json
+++ b/package.json
@@ -1,11 +1,11 @@
{
"name": "nano",
- "description": "minimalistic couchdb driver for node.js",
+ "description": "The official CouchDB client for Node.js",
"license": "Apache-2.0",
- "homepage": "http://github.com/dscape/nano",
- "repository": "git://github.com/dscape/nano",
- "version": "6.1.5",
- "author": "Nuno Job <nunojobpinto@gmail.com> (http://nunojob.com)",
+ "homepage": "http://github.com/apache/couchdb-nano",
+ "repository": "git://github.com/apache/couchdb-nano",
+ "version": "6.2.0",
+ "author": "Apache CouchDB <dev@couchdb.apache.org> (http://couchdb.apache.org)",
"keywords": [
"couchdb",
"data",
@@ -31,8 +31,7 @@
"jscs": "^1.7.0",
"nock": "^0.48.1",
"endswith": "^0.0.0",
- "tape-it": "^0.3.1",
- "pre-commit": "0.0.9"
+ "tape-it": "^0.3.1"
},
"scripts": {
"test": "DEBUG=* NOCK_OFF=true istanbul cover tape tests/*/*/*.js",
diff --git a/tests/fixtures/design/atomic.json b/tests/fixtures/design/atomic.json
index 5a58b91..5712da0 100644
--- a/tests/fixtures/design/atomic.json
+++ b/tests/fixtures/design/atomic.json
@@ -22,6 +22,10 @@
, "response" : "{\"foo\": \"bar\"}"
}
, { "method" : "put"
+ , "path" : "/design_atomic/_design/update/_update/addbaz/baz"
+ , "response" : "{\"baz\": \"biz\"}"
+ }
+, { "method" : "put"
, "status" : 201
, "path" : "/design_atomic/wat%2Fwat"
, "body" : "{\"wat\":\"wat\"}"
diff --git a/tests/integration/design/atomic.js b/tests/integration/design/atomic.js
index 8fedaf1..f948387 100644
--- a/tests/integration/design/atomic.js
+++ b/tests/integration/design/atomic.js
@@ -26,6 +26,10 @@
var body = JSON.parse(req.body);
doc[body.field] = body.value;
return [doc, JSON.stringify(doc)];
+ },
+ addbaz: function (doc, req) {
+ doc.baz = "biz";
+ return [doc, JSON.stringify(doc)];
}
}
}, '_design/update', function(err) {
@@ -51,6 +55,16 @@
});
});
+it('should be able to update atomically without a body', function (assert) {
+ db.insert({}, 'baz', function (error, doc) {
+ db.atomic('update', 'addbaz', 'baz', function (error, response) {
+ assert.equal(error, null, 'should be able to update');
+ assert.equal(response.baz, 'biz', 'and the new field is present');
+ assert.end();
+ });
+ });
+});
+
it('should be able to update with slashes on the id', function(assert) {
db.insert({'wat': 'wat'}, 'wat/wat', function(error, foo) {
assert.equal(error, null, 'stores `wat`');
diff --git a/tests/integration/document/destroy.js b/tests/integration/document/destroy.js
index 0d6bdf7..7e07448 100644
--- a/tests/integration/document/destroy.js
+++ b/tests/integration/document/destroy.js
@@ -29,6 +29,14 @@
});
});
+it('should not delete a db', function(assert) {
+ db.destroy(undefined, undefined, function(error, response) {
+ assert.equal(error, 'Invalid doc id', 'validated delete parameters');
+ assert.equal(response, null, 'ok!');
+ assert.end();
+ });
+});
+
it('should delete a document', function(assert) {
db.destroy('foobaz', rev, function(error, response) {
assert.equal(error, null, 'deleted foo');