Skip to content
This repository has been archived by the owner on Nov 5, 2018. It is now read-only.

Commit

Permalink
# 0.7.0
Browse files Browse the repository at this point in the history
* added support for arbitrary paths in
* document paths are now EncodeURIComponent by default, use path to override
* new error handling code, hopefully more readable
* added auto db.use when a database is present in the uri that was provided
* updated to request 2.1.1 on frozen deps
  • Loading branch information
dscape committed Aug 29, 2011
1 parent 403949c commit ecd5b1a
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 104 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
@@ -0,0 +1,7 @@
# 0.7.0

* added support for arbitrary paths in `nano.request`
* document paths are now EncodeURIComponent by default, use path to override
* new error handling code, hopefully more readable
* added auto db.use when a database is present in the uri that was provided
* updated to request 2.1.1 on frozen deps
18 changes: 9 additions & 9 deletions LICENSE
@@ -1,13 +1,13 @@
Copyright 2011 Nuno Job <nunojob.com>
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
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.
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.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -123,7 +123,7 @@ to get a document in a specific rev an advanced user might do:
function (_,_,b) { console.log(b) }
);

this is the same as (assuming `alice = nano.use("alice");`):
this is the same as (assuming `alice = require('nano')('http://localhost:5984/alice')`):

alice.get("rabbit", {rev: "1-967a00dff5e02add41819138abb3284d"},
function (_,_,b) { console.log(b) }
Expand Down
4 changes: 4 additions & 0 deletions cfg/tests.js
Expand Up @@ -30,4 +30,8 @@ cfg.url = function (){
":" + cfg.port;
}();

cfg.db_url = function (postfix) {
return cfg.url + '/' + postfix;
};

module.exports = exports = cfg;
123 changes: 62 additions & 61 deletions error.js
@@ -1,55 +1,56 @@
var STATUS_CODES = { '100': 'Continue',
'101': 'Switching Protocols',
'102': 'Processing',
'200': 'OK',
'201': 'Created',
'202': 'Accepted',
'203': 'Non-Authoritative Information',
'204': 'No Content',
'205': 'Reset Content',
'206': 'Partial Content',
'207': 'Multi-Status',
'300': 'Multiple Choices',
'301': 'Moved Permanently',
'302': 'Moved Temporarily',
'303': 'See Other',
'304': 'Not Modified',
'305': 'Use Proxy',
'307': 'Temporary Redirect',
'400': 'Bad Request',
'401': 'Unauthorized',
'402': 'Payment Required',
'403': 'Forbidden',
'404': 'Not Found',
'405': 'Method Not Allowed',
'406': 'Not Acceptable',
'407': 'Proxy Authentication Required',
'408': 'Request Time-out',
'409': 'Conflict',
'410': 'Gone',
'411': 'Length Required',
'412': 'Precondition Failed',
'413': 'Request Entity Too Large',
'414': 'Request-URI Too Large',
'415': 'Unsupported Media Type',
'416': 'Requested Range Not Satisfiable',
'417': 'Expectation Failed',
'418': 'I\'m a teapot',
'422': 'Unprocessable Entity',
'423': 'Locked',
'424': 'Failed Dependency',
'425': 'Unordered Collection',
'426': 'Upgrade Required',
'500': 'Internal Server Error',
'501': 'Not Implemented',
'502': 'Bad Gateway',
'503': 'Service Unavailable',
'504': 'Gateway Time-out',
'505': 'HTTP Version not supported',
'506': 'Variant Also Negotiates',
'507': 'Insufficient Storage',
'509': 'Bandwidth Limit Exceeded',
'510': 'Not Extended' };
var STATUS_CODES = { '100': 'Continue'
,'101': 'Switching Protocols'
,'102': 'Processing'
,'200': 'OK'
,'201': 'Created'
,'202': 'Accepted'
,'203': 'Non-Authoritative Information'
,'204': 'No Content'
,'205': 'Reset Content'
,'206': 'Partial Content'
,'207': 'Multi-Status'
,'300': 'Multiple Choices'
,'301': 'Moved Permanently'
,'302': 'Moved Temporarily'
,'303': 'See Other'
,'304': 'Not Modified'
,'305': 'Use Proxy'
,'307': 'Temporary Redirect'
,'400': 'Bad Request'
,'401': 'Unauthorized'
,'402': 'Payment Required'
,'403': 'Forbidden'
,'404': 'Not Found'
,'405': 'Method Not Allowed'
,'406': 'Not Acceptable'
,'407': 'Proxy Authentication Required'
,'408': 'Request Time-out'
,'409': 'Conflict'
,'410': 'Gone'
,'411': 'Length Required'
,'412': 'Precondition Failed'
,'413': 'Request Entity Too Large'
,'414': 'Request-URI Too Large'
,'415': 'Unsupported Media Type'
,'416': 'Requested Range Not Satisfiable'
,'417': 'Expectation Failed'
,'418': 'I\'m a teapot'
,'422': 'Unprocessable Entity'
,'423': 'Locked'
,'424': 'Failed Dependency'
,'425': 'Unordered Collection'
,'426': 'Upgrade Required'
,'500': 'Internal Server Error'
,'501': 'Not Implemented'
,'502': 'Bad Gateway'
,'503': 'Service Unavailable'
,'504': 'Gateway Time-out'
,'505': 'HTTP Version not supported'
,'506': 'Variant Also Negotiates'
,'507': 'Insufficient Storage'
,'509': 'Bandwidth Limit Exceeded'
,'510': 'Not Extended'
};
/*
* generic error
*
Expand Down Expand Up @@ -84,18 +85,18 @@ var STATUS_CODES = { '100': 'Continue',
*
* @return an augmented error that helps you know more than the stack trace
*/
function gen_err(error,code,request,http_code,type) {
if(!type) { type = http_code; http_code = null; }
if(!error) { error = new Error(STATUS_CODES[http_code] || "Unknown Error"); }
if(typeof http_code !== "number") { http_code = 500; }
function gen_err(scope,error,code,request,status_code) {
error = error || STATUS_CODES[status_code] || 'Unknown Error';
code = code || 'unknown';
status_code = typeof status_code === 'number' && status_code || 500;
request = request || {};
if(typeof error === 'string') { error = new Error(error); }

error.error = code;
error.status_code = http_code;
error.namespace = type;
error.status_code = status_code;
error.scope = scope;
error.request = request;
return error;
}

exports.request_err = function (e,c,r,h) { return gen_err(e,c,r,h,"request");};
exports.couch_err = function (e,c,r,h) { return gen_err(e,c,r,h,"couch"); };
exports.request = function (e,c,r,h) { return gen_err('request',e,c,r,h);};
exports.couch = function (e,c,r,h) { return gen_err('couch',e,c,r,h); };
41 changes: 29 additions & 12 deletions nano.js
Expand Up @@ -18,6 +18,7 @@ var request = require('request')
, fs = require('fs')
, qs = require('querystring')
, _ = require('underscore')
, u = require('url')
, error = require('./error')
, default_url = "http://localhost:5984"
, nano;
Expand All @@ -32,24 +33,29 @@ var request = require('request')
* dinosaurs spaceships!
*/
module.exports = exports = nano = function database_module(cfg) {
var public_functions = {};
var public_functions = {}, path, db;
if(typeof cfg === "string") {
if(/^https?:/.test(cfg)) { cfg = {url: cfg}; } // url
else {
try { cfg = require(cfg); } // file path
catch(e) { console.error("bad cfg: couldn't load file"); }
}
}
if(!cfg) {
console.error("bad cfg: you passed undefined");
cfg = {};
}
if(cfg.proxy) {
request = request.defaults({proxy: cfg.proxy}); // proxy support
}
if(!cfg.url) {
console.error("bad cfg: using default=" + default_url);
cfg = {url: default_url}; // if everything else fails, use default
}
path = u.parse(cfg.url);

/****************************************************************************
* relax *
* relax *
****************************************************************************/
/*
* relax
Expand All @@ -71,6 +77,7 @@ module.exports = exports = nano = function database_module(cfg) {
* @param {opts:object} request options; e.g. {db: "test", method: "GET"}
* {opts.db:string} database name
* {opts.method:string:optional} http method, defaults to "GET"
* {opts.path:string:optional} a full path, override `doc` and `att`
* {opts.doc:string:optional} document name
* {opts.att:string:optional} attachment name
* {opts.content_type:string:optional} content type, default to json
Expand All @@ -88,10 +95,13 @@ module.exports = exports = nano = function database_module(cfg) {
, status_code
, parsed
, rh;
if(opts.doc) {
url += "/" + opts.doc; // add the document to the url
if(opts.path) {
url += "/" + opts.path;
}
else if(opts.doc) {
url += "/" + encodeURIComponent(opts.doc); // add the document to the url
if(opts.att) { url += "/" + opts.att; } // add the attachment to the url
}
}
if(opts.encoding && callback) {
req.encoding = opts.encoding;
delete req.headers["content-type"];
Expand All @@ -112,15 +122,15 @@ module.exports = exports = nano = function database_module(cfg) {
request(req, function(e,h,b){
rh = (h && h.headers || {});
rh['status-code'] = status_code = (h && h.statusCode || 500);
if(e) { return callback(error.request_err(e,"socket",req,status_code),rh,b); }
if(e) { return callback(error.request(e,"socket",req,status_code),rh,b); }
delete rh.server; // prevent security vunerabilities related to couchdb
delete rh["content-length"]; // prevent problems with trims and stalled responses
try { parsed = JSON.parse(b); } catch (err) { parsed = b; } // did we get json or binary?
if (status_code >= 200 && status_code < 300) {
callback(null,rh,parsed);
}
else { // proxy the error directly from couchdb
callback(error.couch_err(parsed.reason,parsed.error,req,status_code),rh,parsed);
callback(error.couch(parsed.reason,parsed.error,req,status_code),rh,parsed);
}
});
}
Expand Down Expand Up @@ -211,7 +221,7 @@ module.exports = exports = nano = function database_module(cfg) {
callback = design_name;
design_name = null;
}
return relax({db: db_name, doc: "_compact", att: design_name, method: "POST"},callback);
return relax({db: db_name, path: ("_compact" + design_name), method: "POST"},callback);
}

/*
Expand All @@ -231,7 +241,7 @@ module.exports = exports = nano = function database_module(cfg) {
callback = params;
params = {};
}
return relax({db: db_name, doc: "_changes", params: params, method: "GET"},callback);
return relax({db: db_name, path: "_changes", params: params, method: "GET"},callback);
}

/*
Expand Down Expand Up @@ -331,7 +341,7 @@ module.exports = exports = nano = function database_module(cfg) {
callback = params;
params = {};
}
return relax({db: db_name, doc: "_all_docs", method: "GET", params: params},callback);
return relax({db: db_name, path: "_all_docs", method: "GET", params: params},callback);
}

/*
Expand All @@ -344,7 +354,7 @@ module.exports = exports = nano = function database_module(cfg) {
* @see relax
*/
function bulk_docs(docs,callback) {
return relax({db: db_name, doc: "_bulk_docs", body: docs, method: "POST"},callback);
return relax({db: db_name, path: "_bulk_docs", body: docs, method: "POST"},callback);
}

/**************************************************************************
Expand Down Expand Up @@ -458,7 +468,14 @@ module.exports = exports = nano = function database_module(cfg) {
, relax: relax // alias
, dinosaur: relax // alias
};
return public_functions;

// does the user want a database, or nano?
if(!_.isEmpty(path.pathname.split('/')[1])) {
db = path.pathname.split('/')[1];
cfg.url = path.protocol + '//' + path.host; // reset url
return document_module(db);
}
else { return public_functions; }
};

/*
Expand Down
10 changes: 5 additions & 5 deletions node_modules/request/main.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
@@ -1,10 +1,10 @@
{ "name": "nano"
, "description": "minimalistic couchdb driver for node.js"
, "homepage": "http://github.com/dscape/nano"
, "version": "0.6.6"
, "version": "0.7.0"
, "author": "Nuno Job <nunojobpinto@gmail.com> (http://nunojob.com)"
, "keywords": ["couchdb", "data", "request", "json", "nosql", "micro", "nano"]
, "dependencies": {"request": "~2.0.5", "underscore": "~1.1.7"}
, "dependencies": {"request": "~2.1.1", "underscore": "~1.1.7"}
, "devDependencies": { "async": "~0.1.9", "vows": "~0.5.10" }
, "main": "./nano.js"
, "engines" : { "node": ">=0.3.6" }
Expand Down

0 comments on commit ecd5b1a

Please sign in to comment.