Comparing version 2.1.0 to 2.1.1
18
nano.js
@@ -139,9 +139,2 @@ /* minimal couch in node | ||
} | ||
if(!callback) { // void callback, stream | ||
try { | ||
return request(req); | ||
} catch (ex4) { | ||
return error.request_err(ex4, 'streamthrow', {}); | ||
} | ||
} | ||
if(opts.body) { | ||
@@ -167,2 +160,9 @@ if (Buffer.isBuffer(opts.body)) { | ||
log(req); | ||
if(!callback) { // void callback, stream | ||
try { | ||
return request(req); | ||
} catch (ex4) { | ||
return error.request_err(ex4, 'streamthrow', {}); | ||
} | ||
} | ||
try { | ||
@@ -459,3 +459,3 @@ var stream = request(req, function(e,h,b){ | ||
* | ||
* @param {design_name:string} design document namd | ||
* @param {design_name:string} design document name | ||
* @param {update_name:string} update method to call | ||
@@ -679,2 +679,2 @@ * @param {doc_name:string} document name to update | ||
fs.readFileSync(__dirname + "/package.json")).version; | ||
nano.path = __dirname; | ||
nano.path = __dirname; |
@@ -5,3 +5,3 @@ { "name" : "nano" | ||
, "repository" : "git://github.com/dscape/nano" | ||
, "version" : "2.1.0" | ||
, "version" : "2.1.1" | ||
, "author" : "Nuno Job <nunojobpinto@gmail.com> (http://nunojob.com)" | ||
@@ -21,2 +21,3 @@ , "contributors" : | ||
, "Mark Hahn (http://hahnca.com)" | ||
, "Francesco Ceccon <francesco@ceccon.me> (http://francesco-cek.com/)" | ||
] | ||
@@ -23,0 +24,0 @@ , "keywords" : |
498
README.md
# nano | ||
`nano` (short for `nanocouch`) is a minimalistic `couchdb` driver for `node.js` | ||
minimalistic couchdb driver for node.js | ||
# installation | ||
`nano` features: | ||
* **minimalistic** - there is only a minimun of abstraction between you and | ||
couchdb | ||
* **pipes** - proxy requests from couchdb directly to your end user | ||
* **errors** - errors are proxied directly from couchdb: if you know chouchdb | ||
you already know `nano` | ||
## installation | ||
1. install [npm][1] | ||
2. `npm install nano` | ||
# usage | ||
## getting started | ||
to use `nano` you need to connect it to your couchdb install, to do that: | ||
``` js | ||
var nano = require('nano')('http://localhost:5984'); | ||
var nano = require('nano')('http://localhost:5984'); | ||
``` | ||
within the `nano` variable you have various methods you can call. these include tasks like create, delete or list databases: | ||
to create a new database: | ||
``` js | ||
nano.db.create("alice"); | ||
nano.db.create('alice'); | ||
``` | ||
in this function there is not callback. in `nano` the absence of callback means "do this, ignore what happens" | ||
and to use it: | ||
you normally don't want to do that though: | ||
``` js | ||
var alice = nano.db.use('alice'); | ||
``` | ||
in this examples we didn't specify a `callback` function, the absence of a | ||
callback means _"do this, ignore what happens"_. | ||
in `nano` the callback function receives always three arguments: | ||
* `err` - the error, if any | ||
* `body` - the http _response body_ from couchdb, if no error. | ||
json parsed body, binary for non json responses | ||
* `header` - the http _response header_ from couchdb, if no error | ||
a simple but complete example using callbacks is: | ||
``` js | ||
// clean up the database we created previously | ||
nano.db.destroy("alice", function() { | ||
nano.db.create("alice", function() { | ||
// specify the database we are going to use | ||
var alice = nano.use("alice"); | ||
alice.insert({crazy: true}, "rabbit", function(e,b,h){ | ||
if(e) { throw e; } | ||
console.log("you have inserted the rabbit.") | ||
}); | ||
var nano = require('nano')('http://localhost:5984'); | ||
// clean up the database we created previously | ||
nano.db.destroy('alice', function() { | ||
// create a new database | ||
nano.db.create('alice', function() { | ||
// specify the database we are going to use | ||
var alice = nano.use('alice'); | ||
// and insert a document in it | ||
alice.insert({ crazy: true }, 'rabbit', function(err, body, header) { | ||
if (err) { | ||
console.log('[alice.insert] ', err.message); | ||
return; | ||
} | ||
console.log('you have inserted the rabbit.') | ||
console.log(body); | ||
}); | ||
}); | ||
}); | ||
``` | ||
the `nano.use` method creates a `scope` where you operate inside a single database. this is just a convenience so you don't have to specify the database name every single time you do an update or delete | ||
if you run this example(after starting couchdb) you will see: | ||
you have inserted the rabbit. | ||
{ ok: true, | ||
id: 'rabbit', | ||
rev: '1-6e4cb465d49c0368ac3946506d26335d' } | ||
you can also see your document in [futon](http://localhost:5984/_utils). | ||
## database functions | ||
### nano.db.create(name, [callback]) | ||
creates a couchdb database with the given `name`. | ||
``` js | ||
// 5: var alice = nano.use("alice"); | ||
nano.db.create('alice', function(err, body) { | ||
if (!err) { | ||
console.log('database alice created!'); | ||
} | ||
}); | ||
``` | ||
in `nano` *a callback has always the same three arguments* | ||
### nano.db.get(name, [callback]) | ||
get informations about `name`. | ||
``` js | ||
// 6: alice.insert({crazy: true}, "rabbit", function(e,b,h) { | ||
// 7: if(e) { throw e; } | ||
// 8: console.log("you have inserted the rabbit.") | ||
// 9: }); | ||
nano.db.get('alice', function(err, body) { | ||
if (!err) { | ||
console.log(body); | ||
} | ||
}); | ||
``` | ||
meaning: | ||
### nano.db.destroy(name, [callback]) | ||
e: the `error`, if any | ||
b: the http `response body` from couchdb, if no error. json parsed body, binary for non-json responses | ||
h: the http response `headers` from couchdb, if no error | ||
destroys `name`. | ||
errors include responses from couchdb which had a non 200 response code. that's it. don't forget to delete the database you created: | ||
``` js | ||
nano.db.destroy('alice'); | ||
``` | ||
even though this examples looks sync it is an async function. | ||
### nano.db.list([callback]) | ||
lists all the databases in couchdb | ||
``` js | ||
nano.db.destroy("alice"); | ||
nano.db.list(function(err, body) { | ||
// body is an array | ||
body.forEach(function(db) { | ||
console.log(db); | ||
}); | ||
}); | ||
``` | ||
# tutorials & screencasts | ||
### nano.db.compact(name, [designname], [callback]) | ||
* screencast: [couchdb and nano](http://nodetuts.com/tutorials/30-couchdb-and-nano.html#video) | ||
* article: [nano - a minimalistic couchdb client for nodejs](http://writings.nunojob.com/2011/08/nano-minimalistic-couchdb-client-for-nodejs.html) | ||
* article: [getting started with node.js and couchdb](http://writings.nunojob.com/2011/09/getting-started-with-nodejs-and-couchdb.html) | ||
* article: [Document Update Handler Support](http://jackhq.tumblr.com/post/16035106690/nano-v1-2-x-document-update-handler-support-v1-2-x) | ||
compacts `name`, if `designname` is specified also compacts its | ||
views. | ||
# interfaces | ||
### nano.db.replicate(source, target, [opts], [callback]) | ||
`*` marks optional | ||
`params` are additional querystring parameters | ||
replicates `source` on `target` with options `opts`. `target` | ||
has to exist, add `create_target:true` to `opts` to create it prior to | ||
replication. | ||
## databases, et al | ||
``` js | ||
nano.db.replicate('alice', 'http://admin:password@otherhost.com:5984/alice', | ||
{ create_target:true }, function(err, body) { | ||
if (!err) | ||
console.log(body); | ||
}); | ||
``` | ||
### functions | ||
### nano.db.changes(name, [params], [callback]) | ||
`server.db.create(db_name,callback*)` | ||
`server.db.get(db_name,callback*)` | ||
`server.db.destroy(db_name,callback*)` | ||
`server.db.list(callback*)` | ||
`server.db.compact(db_name,design_name*,callback*)` | ||
`server.db.replicate(source,target,opts*,callback*)` | ||
`server.db.changes(db_name,params*,callback*)` | ||
`server.use(db_name)` | ||
`server.request(opts,callback*)` | ||
`server.config` | ||
asks for the changes feed of `name`, `params` contains additions | ||
to the querystring. | ||
### aliases | ||
``` js | ||
nano.db.changes('alice', function(err, body) { | ||
if (!err) | ||
console.log(body); | ||
}); | ||
``` | ||
`nano.use: [nano.db.use, nano.db.scope, nano.scope]` | ||
`nano.request: [nano.relax, nano.dinosaur]` | ||
### nano.use(name) | ||
## documents, attachments, views, et al | ||
creates a scope where you operate inside `name`. | ||
### functions | ||
``` js | ||
var alice = nano.use('alice'); | ||
alice.insert({ crazy: true }, 'rabbit', function(err, body) { | ||
// do something | ||
}); | ||
``` | ||
`db.insert(doc,doc_name*,callback*)` | ||
`db.destroy(doc_name,rev,callback*)` | ||
`db.get(doc_name,params*,callback*)` | ||
`db.bulk(docs,params*,callback*)` | ||
`db.list(params*,callback*)` | ||
`db.fetch(doc_names,params*,callback*)` | ||
`db.view(design_name,view_name,params*,callback*)` | ||
`db.attachment.insert(doc_name,att_name,att,content_type,params*,callback*)` | ||
`db.attachment.get(doc_name,att_name,params*,callback*)` | ||
`db.attachment.destroy(doc_name,att_name,rev,callback*)` | ||
`db.updateWithHandler(design_name, update_name, doc_name, body*, callback*)` | ||
### nano.db.use(name) | ||
### aliases | ||
alias for `nano.use` | ||
`nano.use` sets `db_name` in scope so you don't have to specify it every time | ||
### nano.db.scope(name) | ||
`server.db.get: [db.info(callback*)]` | ||
`server.db.replicate: [db.replicate(target,opts*,callback*)]` | ||
`server.db.compact: [db.compact(callback*), db.view.compact(design_name,callback*)]` | ||
`server.db.changes: [db.changes(params*,callback*)]` | ||
`server.config: [db.config]` | ||
alias for `nano.use` | ||
## advanced | ||
### nano.scope(name) | ||
`nano` is minimalistic so it provides advanced users with a way to code their own extension functions: | ||
alias for `nano.use` | ||
### nano.request(opts, [callback]) | ||
makes a request to couchdb, the available `opts` are: | ||
* `opts.db` - the database name | ||
* `opts.method` - the http method, defaults to `get` | ||
* `opts.path` - the full path of the request, overrides `opts.doc` and | ||
`opts.att` | ||
* `opts.doc` - the document name | ||
* `opts.att` - the attachment name | ||
* `opts.content_type` - the content type of the request, default to `json` | ||
* `opts.body` - the document or attachment body | ||
* `opts.encoding` - the encoding for attachments | ||
### nano.relax(opts, [callback]) | ||
alias for `nano.request` | ||
### nano.dinosaur(opts, [callback]) | ||
alias for `nano.request` | ||
/ _) roar! i'm a vegan! | ||
.-^^^-/ / | ||
__/ / | ||
/__.|_|-|_| | ||
### nano.config | ||
an object containing the nano configurations, possible keys are: | ||
* `url` - the couchdb url | ||
* `db` - the database name | ||
## document functions | ||
### db.insert(doc, [docname], [callback]) | ||
inserts `doc` in the database with an optional `docname`. | ||
``` js | ||
nano.request(opts,callback*) | ||
var alice = nano.use('alice'); | ||
alice.insert({ crazy: true }, 'rabbit', function(err, body) { | ||
if (!err) | ||
console.log(body); | ||
}); | ||
``` | ||
to get a document in a specific rev an advanced user might do: | ||
### db.destroy(docname, rev, [callback]) | ||
removes revision `rev` of `docname` from couchdb. | ||
``` js | ||
nano.request( { db: "alice" | ||
, doc: "rabbit" | ||
, method: "GET" | ||
, params: { rev: "1-967a00dff5e02add41819138abb3284d"} | ||
}, | ||
function (_,b) { console.log(b) }); | ||
alice.destroy('alice', '3-66c01cdf99e84c83a9b3fe65b88db8c0', function(err, body) { | ||
if (!err) | ||
console.log(body); | ||
}); | ||
``` | ||
this is the same as (assuming `alice = require('nano')('http://localhost:5984/alice')`): | ||
### db.get(docname, [params], [callback]) | ||
gets `docname` from the database with optional querystring | ||
additions `params`. | ||
``` js | ||
alice.get("rabbit", {rev: "1-967a00dff5e02add41819138abb3284d"}, | ||
function (_,b) { console.log(b) }); | ||
alice.get('rabbit', { revs_info: true }, function(err, body) { | ||
if (!err) | ||
console.log(body); | ||
}); | ||
``` | ||
### pipe | ||
### db.bulk(docs, [params], [callback]) | ||
you can pipe in `nano` just like you do in any other stream. this is available in all methods: | ||
bulk operations(update/delete/insert) on the database, refer to the | ||
[couchdb doc](http://wiki.apache.org/couchdb/http_bulk_document_api). | ||
### db.list([params], [callback]) | ||
list all the docs in the database with optional querystring additions `params`. | ||
``` js | ||
alice.attachment.get("breakfast", "sugar", {rev: rev}) | ||
.pipe(fs.createWriteStream("/tmp/sugar-for-rabbit")); | ||
alice.list(function(err, body) { | ||
if (!err) { | ||
body.rows.forEach(function(doc) { | ||
console.log(doc); | ||
}); | ||
} | ||
}); | ||
``` | ||
# roadmap | ||
### db.fetch(docnames, [params], [callback]) | ||
check [issues][2] | ||
bulk fetch of the database documents, `docnames` are specified as per | ||
[couchdb doc](http://wiki.apache.org/couchdb/http_bulk_document_api). | ||
additionals querystring `params` can be specified, `include_doc` is always set | ||
to `true`. | ||
# contribute | ||
## attachments functions | ||
everyone is welcome to contribute. patches, bugfixes, new features | ||
### db.attachment.insert(docname, attname, att, contenttype, [params], [callback]) | ||
1. create an [issue][2] on github so the community can comment on your idea | ||
2. fork `nano` in github | ||
3. create a new branch `git checkout -b my_branch` | ||
4. create tests for the changes you made | ||
5. make sure you pass both existing and newly inserted tests | ||
6. commit your changes | ||
7. push to your branch `git push origin my_branch` | ||
8. create an pull request | ||
inserts an attachment `attname` to `docname`, in most cases | ||
`params.rev` is required. refer to the | ||
[doc](http://wiki.apache.org/couchdb/http_document_api) for more details. | ||
# tests | ||
``` js | ||
var fs = require('fs'); | ||
fs.readFile('rabbit.png', function(err, data) { | ||
if (!err) { | ||
alice.attachment.insert('rabbit', 'rabbit.png', data, 'image/png', | ||
{ rev: '12-150985a725ec88be471921a54ce91452' }, function(err, body) { | ||
if (!err) | ||
console.log(body); | ||
}); | ||
} | ||
}); | ||
``` | ||
or using `pipe`: | ||
``` js | ||
var fs = require('fs'); | ||
fs.createReadStream('rabbit.png').pipe( | ||
alice.attachment.insert('new', 'rab.png', {}, 'image/png') | ||
); | ||
``` | ||
### db.attachment.get(docname, attname, [params], [callback]) | ||
get `docname`'s attachment `attname` with optional querystring additions | ||
`params`. | ||
``` js | ||
var fs = require('fs'); | ||
alice.attachment.get('rabbit', 'rabbit.png', function(err, body) { | ||
if (!err) { | ||
fs.writeFile('rabbit.png', body); | ||
} | ||
}); | ||
``` | ||
or using `pipe`: | ||
``` js | ||
var fs = require('fs'); | ||
alice.attachment.get('rabbit', 'rabbit.png').pipe(fs.createWriteStream('rabbit.png')); | ||
``` | ||
### db.attachment.destroy(docname, attname, rev, [callback]) | ||
destroy attachment `attname` of `docname`'s revision `rev`. | ||
``` js | ||
alice.attachment.destroy('rabbit', 'rabbit.png', | ||
'1-4701d73a08ce5c2f2983bf7c9ffd3320', function(err, body) { | ||
if (!err) | ||
console.log(body); | ||
}); | ||
``` | ||
## views and design functions | ||
### db.view(designname, viewname, [params], [callback]) | ||
calls a view of the specified design with optional querystring additions | ||
`params`. | ||
``` js | ||
alice.view('characters', 'crazy_ones', function(err, body) { | ||
if (!err) { | ||
body.rows.forEach(function(doc) { | ||
console.log(doc.value); | ||
}); | ||
} | ||
}); | ||
``` | ||
### db.updateWithHandler(designname, updatename, docname, [body], [callback]) | ||
calls the design's update function with the specified doc in input. | ||
## advanced features | ||
### extending nano | ||
nano is minimalistic but you can add your own features with | ||
`nano.request(opts, callback)` | ||
for example, to create a function to retrieve a specific revision of the | ||
`rabbit` document: | ||
``` js | ||
function getrabbitrev(rev, callback) { | ||
nano.request({ db: 'alice', | ||
doc: 'rabbit', | ||
method: 'get', | ||
params: { rev: rev } | ||
}, callback); | ||
} | ||
getrabbitrev('4-2e6cdc4c7e26b745c2881a24e0eeece2', function(err, body) { | ||
if (!err) { | ||
console.log(body); | ||
} | ||
}); | ||
``` | ||
### pipes | ||
you can pipe in nano like in any other stream. | ||
for example if our `rabbit` document has an attachment with name `picture.png` | ||
(with a picture of our white rabbit, of course!) you can pipe it to a `writable | ||
stream` | ||
``` js | ||
var fs = require('fs'), | ||
nano = require('nano')('http://127.0.0.1:5984/'); | ||
var alice = nano.use('alice'); | ||
alice.attachment.get('rabbit', 'picture.png').pipe(fs.createWriteStream('/tmp/rabbit.png')); | ||
``` | ||
then open `/tmp/rabbit.png` and you will see the rabbit picture. | ||
## tutorials & screencasts | ||
* screencast: [couchdb and nano](http://nodetuts.com/tutorials/30-couchdb-and-nano.html#video) | ||
* article: [nano - a minimalistic couchdb client for nodejs](http://writings.nunojob.com/2011/08/nano-minimalistic-couchdb-client-for-nodejs.html) | ||
* article: [getting started with node.js and couchdb](http://writings.nunojob.com/2011/09/getting-started-with-nodejs-and-couchdb.html) | ||
* article: [document update handler support](http://jackhq.tumblr.com/post/16035106690/nano-v1-2-x-document-update-handler-support-v1-2-x) | ||
## roadmap | ||
check [issues][2] | ||
## tests | ||
to run (and configure) the test suite simply: | ||
``` sh | ||
cd nano | ||
vi cfg/tests.js | ||
npm install # should install ensure and async, if it doesnt install manually | ||
npm test | ||
cd nano | ||
vi cfg/tests.js | ||
npm install # should install ensure and async, if it doesn't install manually | ||
npm test | ||
``` | ||
@@ -191,3 +437,3 @@ | ||
``` sh | ||
NANO_ENV=testing node tests/doc/list.js list_doc_params | ||
nano_env=testing node tests/doc/list.js list_doc_params | ||
``` | ||
@@ -197,6 +443,20 @@ | ||
# meta | ||
## contribute | ||
everyone is welcome to contribute with patches, bugfixes and new features | ||
1. create an [issue][2] on github so the community can comment on your idea | ||
2. fork `nano` in github | ||
3. create a new branch `git checkout -b my_branch` | ||
4. create tests for the changes you made | ||
5. make sure you pass both existing and newly inserted tests | ||
6. commit your changes | ||
7. push to your branch `git push origin my_branch` | ||
8. create a pull request | ||
## meta | ||
_ | ||
/ _) ROAR! i'm a vegan! | ||
/ _) roar! i'm a vegan! | ||
.-^^^-/ / | ||
@@ -211,3 +471,3 @@ __/ / | ||
`(oO)--',-` in [caos][3] | ||
`(oo)--',-` in [caos][3] | ||
@@ -218,1 +478,17 @@ [1]: http://npmjs.org | ||
[4]: https://github.com/dscape/nano/blob/master/cfg/couch.example.js | ||
## license | ||
copyright 2011 nuno job <nunojob.com> (oo)--',-- | ||
licensed under the apache license, version 2.0 (the "license"); | ||
you may not use this file except in compliance with the license. | ||
you may obtain a copy of the license at | ||
http://www.apache.org/licenses/license-2.0 | ||
unless required by applicable law or agreed to in writing, software | ||
distributed under the license is distributed on an "as is" basis, | ||
without warranties or conditions of any kind, either express or implied. | ||
see the license for the specific language governing permissions and | ||
limitations under the license. |
@@ -65,3 +65,4 @@ var ensure = require('ensure') | ||
if(e2) { callback(e2); } | ||
db("a").attachment.get("new", "att", {rev: b2.rev}).pipe(file_stream); | ||
db("a").attachment.get("new", "att", {rev: b2.rev}) | ||
.pipe(file_stream); | ||
}); | ||
@@ -68,0 +69,0 @@ }); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
132719
2834
491