diff --git a/README.md b/README.md index f6fe6da..aa50afd 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,6 @@ With this method we can send all data necessary to query views in the same struc {db:"developers",design:"basic_info",view:"by_name",args:{reduce:false},request:{keys:["Jane"]}} -## Requirements -Tested on node.js v0.4.7 and CouchDB 1.1.1 - PJsonCouch requires knowing the [CouchDB API](http://techzone.couchbase.com/sites/default/files/uploads/all/documentation/couchbase-api.html) and does not intend to overcome the logic behind the original API. ## How is PJsonCouch organized? @@ -40,73 +37,184 @@ PJsonCouch is inspired on the CouchDB HTTP API structure, so is divide in 4 main How to connect to CouchDB without db definition and request a complex query to `_all_docs` +``` js // Constructor without db definition - var test = PJsonCouch({protocol:"http",host:"127.0.0.1",port:5984}); - + var test = PJsonCouch({ + host : "127.0.0.1", + port : 5984 + }); + // set a DB, this does not have callbackfuntion - test.setDB({db:"thisisatempdb"}); - + test.setDB({ + db : "thisisatempdb" + }); + // Login if your DB is protected - test.login({user:"landeiro",password:"123"},function(r){ + test.login({ + user : "landeiro", + password : "123" + }, function(r) { // Get all docs from DB, supports all args and request data from original couchdb API - test.queryDB({action:"_all_docs", args:{descending:true,startkey:"objmyid6",endkey:"objmyid2"}}, function(r){log("*queryDB start/endkey*",r);}); - test.queryDB({action:"_all_docs", request:{keys:["objmyid1","objmyid7"]}}, function(r){log("*queryDB keys*",r);}); + test.queryDB({ + action : "_all_docs", + args : { + descending : true, + startkey : "objmyid6", + endkey : "objmyid2" + } + }, function(r) { + log("*queryDB start/endkey*", r); + }); + test.queryDB({ + action : "_all_docs", + request : { + keys : ["objmyid1", "objmyid7"] + } + }, function(r) { + log("*queryDB keys*", r); + }); }); - +``` How to connect to CouchDB with db definition and execute some docs operations - var test = PJsonCouch({protocol:"http",host:"127.0.0.1",port:5984,db:"mydatabase"}); +``` js + var test = PJsonCouch({ + host : "127.0.0.1", + port : 5984, + db : "mydatabase" + }); // Docs for test - var docs = [{_id:"objmyid0",a:0},{_id:"objmyid1",a:1},{_id:"objmyid2",a:3}]; + var docs = [{ + _id : "objmyid0", + a : 0 + }, { + _id : "objmyid1", + a : 1 + }, { + _id : "objmyid2", + a : 3 + }]; - // Save bulk, supports all request data from original couchdb API - test.saveBulkDocs({docs:docs},function(r){ - log("insert bulk",r); - // Get Doc, supports all arguments from original couchdb API - test.getDoc({id:"objmyid0"},function (gdoc) { - log("*get doc*",gdoc) - if (!gdoc.error) { - // Delete a Doc, supports all arguments from original couchdb API - test.deleteDoc({doc:gdoc}, function (r) { log("*deleted "+gdoc._id+"*",r);}); - } - }); + // Save bulk, supports all request data from original couchdb API + test.saveBulkDocs({ + docs : docs + }, function(r) { + log("insert bulk", r); + // Get Doc, supports all arguments from original couchdb API + test.getDoc({ + id : "objmyid0" + }, function(gdoc) { + log("*get doc*", gdoc) + if(!gdoc.error) { + // Delete a Doc, supports all arguments from original couchdb API + test.deleteDoc({ + doc : gdoc + }, function(r) { + log("*deleted " + gdoc._id + "*", r); + }); + } + }); }); +``` Some random server operations - - test.server({},function (r) {log("*welcome msg*",r);}); +``` js + test.server({}, function(r) { + log("*welcome msg*", r); + }); + // Show active tasks - test.server({action:"_active_tasks"},function (r) {log("*active tasks*",r);}); + test.server({ + action : "_active_tasks" + }, function(r) { + log("*active tasks*", r); + }); + // Start continuos replication database. Replication supports all configuration from original couchdb API - test.server({action:"_replicate",source:"thisisatempdb",target:"http://somedomain.com/land",continuous:true},function (r) { - log("*replicate*",r); + test.server({ + action : "_replicate", + source : "thisisatempdb", + target : "http://somedomain.com/land", + continuous : true + }, function(r) { + log("*replicate*", r); // Cancel continuos replication database, supports all configuration from original couchdb API - test.server({action:"_replicate",source:"thisisatempdb",target:"http://somedomain.com/land",continuous:true,cancel:true},function (r) {log("*cancel replication*",r);}) - + test.server({ + action : "_replicate", + source : "thisisatempdb", + target : "http://somedomain.com/land", + continuous : true, + cancel : true + }, function(r) { + log("*cancel replication*", r); + }) }); - +``` Some random design doc operations +``` js // List customers using view by_name from "Jane" to "Pedro" - test.queryDesign({design:"design_doc",list:"customers",view:"by_name",args:{startkey:"Jane",endkey:"Pedro"}},function (r) {log("*get list with view with args*",r);}); - + test.queryDesign({ + design : "design_doc", + list : "customers", + view : "by_name", + args : { + startkey : "Jane", + endkey : "Pedro" + } + }, function(r) { + log("*get list with view with args*", r); + }); // Display a Doc using Show costumer, supports all arguments from original couchdb API - test.queryDesign({design:"design_doc",show:"customer",id:"3535e007bd9c765de0554c0a4900385b"},function (r) {log("*get show*",r);}); - - // Getting docs using view by_name with request keys ["Jane"] and argument limit=1 - test.queryDesign({design:"design_doc",view:"by_name",args:{limit:1},request:{keys:["Jane","joey"]}},function (r) {log("*get view with request and args*",r);}); - + test.queryDesign({ + design : "design_doc", + show : "customer", + id : "3535e007bd9c765de0554c0a4900385b" + }, function(r) { + log("*get show*", r); + }); + // Getting docs using view by_name with request keys ["Jane"] and argument limit=1 + test.queryDesign({ + design : "design_doc", + view : "by_name", + args : { + limit : 1 + }, + request : { + keys : ["Jane", "joey"] + } + }, function(r) { + log("*get view with request and args*", r); + }); +``` + +GeoCouch Integration + +``` js + // Make a bounding box request + test.queryDesign({ + db : "places", + design : "main", + spatial : "points", + args : { + bbox : "0,0,180,90" + } + }, function(data) { + console.log(data); + }); +``` ### Errors can be configured to return a lot of debug, like request content and headers. Cannot connect do CouchDB - + +``` js { error: 'request_to_couchdb', detail: { stack: 'Error: ECONNREFUSED, Connection refused\n at Socket._onConnect (net.js:576:18)\n at IOWatcher.onWritable [as callback] (net.js:165:12)', @@ -148,7 +256,7 @@ Unauthorized 'content-type': 'text/plain;charset=utf-8', 'content-length': '64', 'cache-control': 'must-revalidate' } } } - +``` See more examples [here](https://github.com/landeiro/PJsonCouch/wiki/PJsonCouch). diff --git a/lib/PJsonCouch.js b/lib/PJsonCouch.js index 1fecf91..361ab5c 100644 --- a/lib/PJsonCouch.js +++ b/lib/PJsonCouch.js @@ -34,6 +34,7 @@ methods["_restart"] = "POST"; methods["_stats"] = "GET"; methods["_uuids"] = "GET"; methods["_info"] = "GET"; +methods["_spatial_cleanup"] = "POST"; var methodsWithRequest = []; methodsWithRequest["_security"] = "PUT"; @@ -46,532 +47,531 @@ methodsWithRequest["_temp_view"] = "POST"; methodsWithRequest["_replicate"] = "POST"; var Utils = { - clone: function (obj) { - var target = {}; - for (var i in obj) { - if (obj.hasOwnProperty(i)) { - target[i] = obj[i]; - } - } - return target; - - }, - - smartQueryStringAux: function (value) { - return (typeof value === "string") ? '"' + encodeURIComponent(value) + '"' : encodeURIComponent(value); - }, - - smartQueryString: function (query) { - if (query === "") return ""; - var qstring = ""; - for (key in query) { - if (qstring !== "") { - qstring += "&"; - } - if (query[key] && query[key].length > 0 && (typeof query[key] !== "string")) { - qstring += key + '=['; - for (keyArray in query[key]) { - if (qstring.charAt(qstring.length - 1) !== '[') { - qstring += ','; - } - qstring += Utils.smartQueryStringAux(query[key][keyArray]); - } - qstring += ']'; - } else if (typeof query[key] === "string" && key.search(/key/gi) !== -1) { - qstring += key + '=' + Utils.smartQueryStringAux(query[key]); - } else { - qstring += key + '=' + encodeURIComponent(query[key]); - } - } - return qstring; - }, - - decodeGetDataAux: function (content, qstring, bool) { - if (!bool) { - return (content === undefined ? "" : qstring + content); - } else { - return (content !== true ? "" : qstring); - } - }, - - decodeGetData: function (url) { - var qstring = ""; - - if (url.serverAction) { - qstring += (Utils.decodeGetDataAux(url.serverAction, "/")); - return qstring; - } - qstring += (Utils.decodeGetDataAux(url.db, "/")); - qstring += (Utils.decodeGetDataAux(url.local, "/_local", true)); - qstring += (Utils.decodeGetDataAux(url.design, "/_design/")); - qstring += (Utils.decodeGetDataAux(url.show, "/_show/")); - qstring += (Utils.decodeGetDataAux(url.list, "/_list/")); - (qstring.indexOf("/_list/") !== -1) ? qstring += (Utils.decodeGetDataAux(url.view, "/")) : qstring += (Utils.decodeGetDataAux(url.view, "/_view/")); - qstring += (Utils.decodeGetDataAux(url.action, "/")); - qstring += (Utils.decodeGetDataAux(url.id, "/")); - qstring += (Utils.decodeGetDataAux(url.attachment, "/")); - - return qstring; - }, - - setJSONError: function (option, result) { - return { - content_type: option.content_type, - length: option.content_length, - not_json: result - }; - }, - - insertExtraInfo: function (result, data, option, resOptions, config) { - try { - result = JSON.parse(result); - } catch (err) { - result = Utils.setJSONError(option, result); - }; - if (typeof result !== "object") result = Utils.setJSONError(option, result); - - if (config.debug || (result.error && config.debugOnError)) { - result.debug = {}; - - if (data) { - result.debug.content = data; - } - - if (result.error && config.throwExceptionsOnError) { - throw new Error("{PJsonCouch Exception:" + JSON.stringify(result) + "}"); - } - result.debug.request = option; - - if (config.debugWithHeaders && resOptions) { - result.debug.resultHeaders = resOptions.headers; - } - } - - if (option.requireHeaders && resOptions) { - result.headers = resOptions.headers; - } - return result; - }, - - request: function (reqOptions, data, reqConfig, callBackFunction) { - var result = ""; - data = data || ""; - - // add the content length header - reqOptions.headers['Content-Length'] = unescape(encodeURIComponent(data)).length; - - var req = http.request(reqOptions, function (res) { - (reqOptions.resultEncoding) ? res.setEncoding(reqOptions.resultEncoding) : res.setEncoding('utf8'); - res.on('data', function (chunk) { - result += chunk; - }); - res.on('end', function () { - if (reqOptions.method === "HEAD") { - callBackFunction(Utils.insertExtraInfo(JSON.stringify(res.headers), {}, reqOptions, res, reqConfig)); - } else { - if (res.headers["Content-Type"] !== "application/json") { - reqOptions.content_type = res.headers["content-type"]; - reqOptions.content_length = res.headers["content-length"]; - } - callBackFunction(Utils.insertExtraInfo(result, data, reqOptions, res, reqConfig)); - } - }); - res.on('error', function (err) { - callBackFunction(Utils.insertExtraInfo(JSON.stringify({ - error: 'response_from_couchdb', - detail: err - }), data, reqOptions, false, reqConfig)); - }); - }).on('error', function (err) { - callBackFunction(Utils.insertExtraInfo(JSON.stringify({ - error: 'request_to_couchdb', - detail: err - }), data, reqOptions, false, reqConfig)); - }); - if (reqOptions.method === "PUT" || reqOptions.method === "POST") { - req.write(data, ((reqOptions.requestEncoding) ? reqOptions.requestEncoding : 'utf8')); - } - req.end(); - } + clone : function(obj) { + var target = {}; + for(var i in obj) { + if(obj.hasOwnProperty(i)) { + target[i] = obj[i]; + } + } + return target; + + }, + smartQueryStringAux : function(value) { + return ( typeof value === "string") ? '"' + encodeURIComponent(value) + '"' : encodeURIComponent(value); + }, + smartQueryString : function(query) { + if(query === "") + return ""; + var qstring = ""; + for(key in query) { + if(qstring !== "") { + qstring += "&"; + } + if(query[key] && query[key].length > 0 && ( typeof query[key] !== "string")) { + qstring += key + '=['; + for(keyArray in query[key]) { + if(qstring.charAt(qstring.length - 1) !== '[') { + qstring += ','; + } + qstring += Utils.smartQueryStringAux(query[key][keyArray]); + } + qstring += ']'; + } else if( typeof query[key] === "string" && key.search(/key/gi) !== -1) { + qstring += key + '=' + Utils.smartQueryStringAux(query[key]); + } else { + qstring += key + '=' + encodeURIComponent(query[key]); + } + } + return qstring; + }, + decodeGetDataAux : function(content, qstring, bool) { + if(!bool) { + return (content === undefined ? "" : qstring + content); + } else { + return (content !== true ? "" : qstring); + } + }, + decodeGetData : function(url) { + var db = Utils.decodeGetDataAux(url.db, "/"), + design = Utils.decodeGetDataAux(url.design, "/_design/"), + local = Utils.decodeGetDataAux(url.local, "/_local", true), + show = Utils.decodeGetDataAux(url.show, "/_show/"), + list = Utils.decodeGetDataAux(url.list, "/_list/"), + action = Utils.decodeGetDataAux(url.action, "/"), + serverAction = Utils.decodeGetDataAux(url.serverAction, "/"), + id = Utils.decodeGetDataAux(url.id, "/"), + attachment = Utils.decodeGetDataAux(url.attachment, "/"), view = "", spatial = ""; + + if(url.list) { + view = Utils.decodeGetDataAux(url.view, "/"); + } else { + view = Utils.decodeGetDataAux(url.view, "/_view"); + } + + if(url.spatial && url.list) { + list = Utils.decodeGetDataAux(url.list, "/_spatial/_list/"); + list = Utils.decodeGetDataAux("/" + url.spatial, list); + } else if(url.spatial && url.action) { + spatial = "/_spatial"; + } else { + spatial = Utils.decodeGetDataAux(url.spatial, "/_spatial/"); + } + + var result = serverAction + db + design + local + show + list + view + spatial + action + id + attachment; + + return result; + }, + setJSONError : function(option, result) { + return { + content_type : option.content_type, + length : option.content_length, + not_json : result + }; + }, + insertExtraInfo : function(result, data, option, resOptions, config) { + try { + result = JSON.parse(result); + } catch (err) { + result = Utils.setJSONError(option, result); + }; + if( typeof result !== "object") + result = Utils.setJSONError(option, result); + + if(config.debug || (result.error && config.debugOnError)) { + result.debug = {}; + + if(data) { + result.debug.content = data; + } + + if(result.error && config.throwExceptionsOnError) { + throw new Error("{PJsonCouch Exception:" + JSON.stringify(result) + "}"); + } + result.debug.request = option; + + if(config.debugWithHeaders && resOptions) { + result.debug.resultHeaders = resOptions.headers; + } + } + + if(option.requireHeaders && resOptions) { + result.headers = resOptions.headers; + } + return result; + }, + request : function(reqOptions, data, reqConfig, callBackFunction) { + var result = ""; + data = data || ""; + + // for 0.6 version + delete reqOptions.protocol; + + // add the content length header + reqOptions.headers['Content-Length'] = unescape(encodeURIComponent(data)).length; + + var req = http.request(reqOptions, function(res) {(reqOptions.resultEncoding) ? res.setEncoding(reqOptions.resultEncoding) : res.setEncoding('utf8'); + res.on('data', function(chunk) { + result += chunk; + }); + res.on('end', function() { + if(reqOptions.method === "HEAD") { + callBackFunction(Utils.insertExtraInfo(JSON.stringify(res.headers), {}, reqOptions, res, reqConfig)); + } else { + if(res.headers["Content-Type"] !== "application/json") { + reqOptions.content_type = res.headers["content-type"]; + reqOptions.content_length = res.headers["content-length"]; + } + callBackFunction(Utils.insertExtraInfo(result, data, reqOptions, res, reqConfig)); + } + }); + res.on('error', function(err) { + callBackFunction(Utils.insertExtraInfo(JSON.stringify({ + error : 'response_from_couchdb', + detail : err + }), data, reqOptions, false, reqConfig)); + }); + }).on('error', function(err) { + callBackFunction(Utils.insertExtraInfo(JSON.stringify({ + error : 'request_to_couchdb', + detail : err + }), data, reqOptions, false, reqConfig)); + }); + if(reqOptions.method === "PUT" || reqOptions.method === "POST") { + req.write(data, ((reqOptions.requestEncoding) ? reqOptions.requestEncoding : 'utf8')); + } + req.end(); + } }; - -var PJsonCouch = function (options) { - - // initialise options defaults - options.headers = options.headers || {}; - options.path = options.path || ''; - var pjs = this; - if (this instanceof PJsonCouch) { - - this.setDB = function (dbObj) { - myDB = dbObj.db; - }; - - this.getDB = function () { - return { - db: myDB - }; - }; - - this.getSession = function () { - return { - AuthSession: mySession - }; - }; - - - var myDB = options.db; - var mySession = ""; - var myCredentials = {}; - var revalidateLoginTimer = ""; - - - var config = { - debug: false, - debugWithHeaders: false, - debugOnError: false, - throwExceptionsOnError: false - }; - - this.setDebugConfig = function (argCfg) { - for (var argKey in argCfg) { - if (config.hasOwnProperty(argKey)) config[argKey] = argCfg[argKey]; - } - }; - - this.getDebugConfig = function () { - return config; - }; - - this.login = function (credentials, callBackFunction) { - var postOptions = this.buildRequest("POST", { - serverAction: "_session" - }); - - if (credentials.revalidateAfter) { - var revalidateAfter = (credentials.revalidateAfter * 1000); - delete credentials.revalidateAfter; - revalidateLoginTimer = setInterval(function() {pjs.login(credentials)}, revalidateAfter); - - } - postOptions.headers = {}; - postOptions.headers["Content-Type"] = "application/x-www-form-urlencoded"; - var loginWith = "name=" + credentials.user + "&password=" + credentials.password; - postOptions.requireHeaders = true; - Utils.request(postOptions, loginWith, config, function (res) { - if (res && res.headers && res.headers["set-cookie"]) { - var cookie = res.headers["set-cookie"][0]; - mySession = cookie.split("=")[1].split(";")[0]; - } - if (callBackFunction) { - if (revalidateAfter) { - res.revalidateAfter = revalidateAfter; - } - callBackFunction(res); - } - }); - }; - - this.logout = function (callBackFunction) { - var reqOptions = this.buildRequest("DELETE", { - serverAction: "_session" - }); - Utils.request(reqOptions, "", config, function (logoutResult) { - if (logoutResult.ok) { - mySession = ""; - if (revalidateLoginTimer !== "") - clearInterval(revalidateLoginTimer); - } - if (callBackFunction) { - callBackFunction(logoutResult); - } - }); - }; - - this.createDB = function (url, callBackFunction) { - var reqOptions = this.buildRequest("PUT", url); - Utils.request(reqOptions, "", config, function (dbInfo) { - if (callBackFunction) { - callBackFunction(dbInfo); - } - }); - }; - - this.deleteDB = function (url, callBackFunction) { - var reqOptions = this.buildRequest("DELETE", url); - Utils.request(reqOptions, "", config, function (dbInfo) { - if (callBackFunction) { - callBackFunction(dbInfo); - } - }); - }; - - this.queryDB = function (url, callBackFunction) { - var method = (url.request) ? methodsWithRequest[url.action] : methods[url.action]; - var reqOptions = this.buildRequest(method, url); - Utils.request(reqOptions, JSON.stringify(url.request), config, function (dbInfo) { - if (callBackFunction) { - callBackFunction(dbInfo); - } - }); - }; - - this.saveDoc = function (url, callBackFunction) { - var putOptions; - - if (typeof url.doc === "string") { - url.doc = JSON.parse(url.doc); - } - if (url.local) { - url.doc._id = url.doc._id.replace(/_local\//, ""); - url.action = encodeURIComponent(url.doc._id); - - putOptions = this.buildRequest("PUT", url); - Utils.request(putOptions, JSON.stringify(url.doc), config, function (result) { - if (callBackFunction) { - callBackFunction(result); - } - }); - } else if (url.doc._id) { - url.action = encodeURIComponent(url.doc._id); - - putOptions = this.buildRequest("PUT", url); - Utils.request(putOptions, JSON.stringify(url.doc), config, function (result) { - if (callBackFunction) { - callBackFunction(result); - } - }); - } else { - var that = this; - this.server({ - action: "_uuids" - }, function (u) { - url.action = encodeURIComponent(u.uuids[0]); - var putOptions = that.buildRequest("PUT", url); - Utils.request(putOptions, JSON.stringify(url.doc), config, function (result) { - if (callBackFunction) { - callBackFunction(result); - } - }); - - }); - } - }; - - this.saveDocAttachment = function (url, callBackFunction) { - url.args = {}; - url.args.rev = url.rev; - if (url.id) { - url.id = encodeURIComponent(url.id); - } - var type = url.attachment.content_type; - var length = url.attachment.content_length; - var ifMatch = url.attachment.if_match; - var content = url.attachment.content; - var encoding = url.attachment.content_encoding; - url.attachment = url.attachment.file; - var putOptions = this.buildRequest("PUT", url); - putOptions.requestEncoding = encoding; - putOptions.headers["Content-Type"] = type; - if (length) { - putOptions.headers["Content-Length"] = length; - } - if (ifMatch) { - putOptions.headers["If-Match"] = ifMatch; - } - Utils.request(putOptions, content, config, function (result) { - if (callBackFunction) { - callBackFunction(result); - } - }); - - }; - - this.deleteDocAttachment = function (url, callBackFunction) { - if (url.rev) { - url.args = {}; - url.args.rev = url.rev; - } - if (url.id) { - url.id = encodeURIComponent(url.id); - } - url.attachment = url.attachment.file; - var deleteOptions = this.buildRequest("DELETE", url); - Utils.request(deleteOptions, "", config, function (result) { - if (callBackFunction) { - callBackFunction(result); - } - }); - - }; - - this.deleteDoc = function (url, callBackFunction) { - if (url.local) { - url.action = encodeURIComponent(url.doc._id); - url.args = {}; - url.args.rev = url.doc._rev; - } else { - url.doc._deleted = true; - } - var postdeleteOptions = this.buildRequest((url.local) ? "DELETE" : "POST", url); - Utils.request(postdeleteOptions, JSON.stringify(url.doc), config, function (result) { - if (callBackFunction) { - callBackFunction(result); - } - }); - }; - - this.getDoc = function (url, callBackFunction) { - if (url.id) { - url.id = encodeURIComponent(url.id); - } - - var getOptions = this.buildRequest("GET", url, options); - Utils.request(getOptions, "", config, function (doc) { - if (callBackFunction) { - callBackFunction(doc); - } - }); - }; - - this.getDocAttachment = function (url, callBackFunction) { - if (url.id) { - url.id = encodeURIComponent(url.id); - } - var encoding = url.attachment.content_encoding; - url.attachment = url.attachment.file; - var getOptions = this.buildRequest("GET", url); - getOptions.resultEncoding = encoding; - Utils.request(getOptions, "", config, function (doc) { - if (callBackFunction) callBackFunction(doc); - }); - }; - - this.infoDoc = function (url, callBackFunction) { - var headOptions = this.buildRequest("HEAD", url); - Utils.request(headOptions, "", config, function (result) { - if (callBackFunction) { - callBackFunction(result); - } - }); - }; - - this.copyDoc = function (url, callBackFunction) { - url.source.id = encodeURIComponent(url.source.id); - url.destination.id = encodeURIComponent(url.destination.id); - if (url.local) { - url.source.id = url.source.id.replace(/_local\//, ""); - url.destination.id = "_local/" + url.destination.id; - } - url.action = url.source.id; - if (url.source.rev) { - url.args = {}; - if (!url.local) {// local does not support revs by url - url.args.rev = url.source.rev; - } - } - var copyOptions = this.buildRequest("COPY", url); - copyOptions.headers.destination = url.destination.id + ((url.destination.rev) ? "?rev=" + url.destination.rev : ""); - Utils.request(copyOptions, "", config, function (result) { - if (callBackFunction) { - callBackFunction(result); - } - }); - }; - - this.saveBulkDocs = function (url, callBackFunction) { - var result = ""; - url.action = '_bulk_docs'; - var postOptions = this.buildRequest("POST", url); - var extraParams = url.args; - var docs = {}; - - docs["docs"] = url.docs; - for (var idx in url.args) { - docs[idx] = url.args[idx]; - - } - - docs = JSON.stringify(docs); - - Utils.request(postOptions, docs, config, function (result) { - if (callBackFunction) { - callBackFunction(result); - } - }); - }; - - this.server = function (url, callBackFunction) { - var data = {}; - url.serverAction = url.action; - for (var idx in url) { - if (idx !== "action" && idx !== "serverAction") { - data[idx] = url[idx]; - } - } - var serverOptions = this.buildRequest(methods[url.action], url); - if (serverOptions.method !== "PUT" && serverOptions.method !== "POST") { - data = ""; - } - Utils.request(serverOptions, JSON.stringify(data), config, function (result) { - if (callBackFunction) { - callBackFunction(result); - } - }); - - }; - - this.infoDesign = function (url, callBackFunction) { - url.action = "_info"; - var designOptions = this.buildRequest(methods[url.action], url); - Utils.request(designOptions, "", config, function (result) { - if (callBackFunction) { - callBackFunction(result); - } - }); - }; - - this.queryDesign = function (url, callBackFunction) { - url.stringifyRequest = true; - var designOptions = this.buildRequest((url.request) ? "POST" : methods[url.action], url); - Utils.request(designOptions, JSON.stringify(url.request), config, function (result) { - if (callBackFunction) { - callBackFunction(result); - } - }); - }; - - this.buildRequest = function (method, url) { - if (!url.db && !url.serverAction) url.db = myDB; - - // dealing with the 'order feature' reported here: http://bit.ly/r1yipp - if (url && url.args && url.args.group_level && url.args.group) { - delete url.args.group; - } - - var qsparams = Utils.smartQueryString(url.args), - reqOpts = Utils.clone(options); - - reqOpts.path += Utils.decodeGetData(url); - reqOpts.method = method; - reqOpts.path = (qsparams === "") ? reqOpts.path : reqOpts.path + "?" + qsparams; - - if (method !== "GET") { - reqOpts.headers["Content-Type"] = "application/json"; - } - - if (mySession !== "") { - reqOpts.headers["Cookie"] = "AuthSession=" + mySession; - } - - reqOpts.headers["User-Agent"] = "PJsonCouch (node.js client for CouchDB) https://github.com/landeiro/PJsonCouch "; - - return reqOpts; - }; - } else { - return new PJsonCouch(options); - } +var PJsonCouch = function(options) { + + // initialise options defaults + options.headers = options.headers || {}; + options.path = options.path || ''; + var pjs = this; + if(this instanceof PJsonCouch) { + + this.setDB = function(dbObj) { + myDB = dbObj.db; + }; + + this.getDB = function() { + return { + db : myDB + }; + }; + + this.getSession = function() { + return { + AuthSession : mySession + }; + }; + var myDB = options.db; + var mySession = ""; + var myCredentials = {}; + var revalidateLoginTimer = ""; + var config = { + debug : false, + debugWithHeaders : false, + debugOnError : false, + throwExceptionsOnError : false + }; + + this.setDebugConfig = function(argCfg) { + for(var argKey in argCfg) { + if(config.hasOwnProperty(argKey)) + config[argKey] = argCfg[argKey]; + } + }; + + this.getDebugConfig = function() { + return config; + }; + + this.login = function(credentials, callBackFunction) { + var postOptions = this.buildRequest("POST", { + serverAction : "_session" + }); + if(credentials.revalidateAfter) { + var revalidateAfter = (credentials.revalidateAfter * 1000); + delete credentials.revalidateAfter; + revalidateLoginTimer = setInterval(function() { + pjs.login(credentials) + }, revalidateAfter); + } + postOptions.headers = {}; + postOptions.headers["Content-Type"] = "application/x-www-form-urlencoded"; + var loginWith = "name=" + credentials.user + "&password=" + credentials.password; + postOptions.requireHeaders = true; + Utils.request(postOptions, loginWith, config, function(res) { + if(res && res.headers && res.headers["set-cookie"]) { + var cookie = res.headers["set-cookie"][0]; + mySession = cookie.split("=")[1].split(";")[0]; + } + if(callBackFunction) { + if(revalidateAfter) { + res.revalidateAfter = revalidateAfter; + } + callBackFunction(res); + } + }); + }; + + this.logout = function(callBackFunction) { + var reqOptions = this.buildRequest("DELETE", { + serverAction : "_session" + }); + Utils.request(reqOptions, "", config, function(logoutResult) { + if(logoutResult.ok) { + mySession = ""; + if(revalidateLoginTimer !== "") + clearInterval(revalidateLoginTimer); + } + if(callBackFunction) { + callBackFunction(logoutResult); + } + }); + }; + + this.createDB = function(url, callBackFunction) { + var reqOptions = this.buildRequest("PUT", url); + Utils.request(reqOptions, "", config, function(dbInfo) { + if(callBackFunction) { + callBackFunction(dbInfo); + } + }); + }; + + this.deleteDB = function(url, callBackFunction) { + var reqOptions = this.buildRequest("DELETE", url); + Utils.request(reqOptions, "", config, function(dbInfo) { + if(callBackFunction) { + callBackFunction(dbInfo); + } + }); + }; + + this.queryDB = function(url, callBackFunction) { + var method = (url.request) ? methodsWithRequest[url.action] : methods[url.action]; + var reqOptions = this.buildRequest(method, url); + Utils.request(reqOptions, JSON.stringify(url.request), config, function(dbInfo) { + if(callBackFunction) { + callBackFunction(dbInfo); + } + }); + }; + + this.saveDoc = function(url, callBackFunction) { + var putOptions; + + if( typeof url.doc === "string") { + url.doc = JSON.parse(url.doc); + } + if(url.local) { + url.doc._id = url.doc._id.replace(/_local\//, ""); + url.id = encodeURIComponent(url.doc._id); + putOptions = this.buildRequest("PUT", url); + Utils.request(putOptions, JSON.stringify(url.doc), config, function(result) { + if(callBackFunction) { + callBackFunction(result); + } + }); + } else if(url.doc._id) { + url.action = encodeURIComponent(url.doc._id); + putOptions = this.buildRequest("PUT", url); + Utils.request(putOptions, JSON.stringify(url.doc), config, function(result) { + if(callBackFunction) { + callBackFunction(result); + } + }); + } else { + var that = this; + this.server({ + action : "_uuids" + }, function(u) { + url.action = encodeURIComponent(u.uuids[0]); + var putOptions = that.buildRequest("PUT", url); + Utils.request(putOptions, JSON.stringify(url.doc), config, function(result) { + if(callBackFunction) { + callBackFunction(result); + } + }); + }); + } + }; + + this.saveDocAttachment = function(url, callBackFunction) { + url.args = {}; + url.args.rev = url.rev; + if(url.id) { + url.id = encodeURIComponent(url.id); + } + var type = url.attachment.content_type; + var length = url.attachment.content_length; + var ifMatch = url.attachment.if_match; + var content = url.attachment.content; + var encoding = url.attachment.content_encoding; + url.attachment = url.attachment.file; + var putOptions = this.buildRequest("PUT", url); + putOptions.requestEncoding = encoding; + putOptions.headers["Content-Type"] = type; + if(length) { + putOptions.headers["Content-Length"] = length; + } + if(ifMatch) { + putOptions.headers["If-Match"] = ifMatch; + } + Utils.request(putOptions, content, config, function(result) { + if(callBackFunction) { + callBackFunction(result); + } + }); + }; + + this.deleteDocAttachment = function(url, callBackFunction) { + if(url.rev) { + url.args = {}; + url.args.rev = url.rev; + } + if(url.id) { + url.id = encodeURIComponent(url.id); + } + url.attachment = url.attachment.file; + var deleteOptions = this.buildRequest("DELETE", url); + Utils.request(deleteOptions, "", config, function(result) { + if(callBackFunction) { + callBackFunction(result); + } + }); + }; + + this.deleteDoc = function(url, callBackFunction) { + if(url.local) { + url.action = encodeURIComponent(url.doc._id); + url.args = {}; + url.args.rev = url.doc._rev; + } else { + url.doc._deleted = true; + } + var postdeleteOptions = this.buildRequest((url.local) ? "DELETE" : "POST", url); + Utils.request(postdeleteOptions, JSON.stringify(url.doc), config, function(result) { + if(callBackFunction) { + callBackFunction(result); + } + }); + }; + + this.getDoc = function(url, callBackFunction) { + if(url.id) { + url.id = encodeURIComponent(url.id); + } + + var getOptions = this.buildRequest("GET", url, options); + Utils.request(getOptions, "", config, function(doc) { + if(callBackFunction) { + callBackFunction(doc); + } + }); + }; + + this.getDocAttachment = function(url, callBackFunction) { + if(url.id) { + url.id = encodeURIComponent(url.id); + } + var encoding = url.attachment.content_encoding; + url.attachment = url.attachment.file; + var getOptions = this.buildRequest("GET", url); + getOptions.resultEncoding = encoding; + Utils.request(getOptions, "", config, function(doc) { + if(callBackFunction) + callBackFunction(doc); + }); + }; + + this.infoDoc = function(url, callBackFunction) { + var headOptions = this.buildRequest("HEAD", url); + Utils.request(headOptions, "", config, function(result) { + if(callBackFunction) { + callBackFunction(result); + } + }); + }; + + this.copyDoc = function(url, callBackFunction) { + if(url.local) { + url.source.id = url.source.id.replace(/_local\//, ""); + } + url.source.id = encodeURIComponent(url.source.id); + url.destination.id = encodeURIComponent(url.destination.id); + url.action = url.source.id; + if(url.source.rev) { + url.args = {}; + if(!url.local) {// local does not support revs by url + url.args.rev = url.source.rev; + } + } + var copyOptions = this.buildRequest("COPY", url); + copyOptions.headers.destination = url.destination.id + ((url.destination.rev) ? "?rev=" + url.destination.rev : ""); + Utils.request(copyOptions, "", config, function(result) { + if(callBackFunction) { + callBackFunction(result); + } + }); + }; + + this.saveBulkDocs = function(url, callBackFunction) { + var result = ""; + url.action = '_bulk_docs'; + var postOptions = this.buildRequest("POST", url); + var extraParams = url.args; + var docs = {}; + + docs["docs"] = url.docs; + for(var idx in url.args) { + docs[idx] = url.args[idx]; + + } + docs = JSON.stringify(docs); + + Utils.request(postOptions, docs, config, function(result) { + if(callBackFunction) { + callBackFunction(result); + } + }); + }; + + this.server = function(url, callBackFunction) { + var data = {}; + url.serverAction = url.action; + delete url.action; + for(var idx in url) { + if(idx !== "action" && idx !== "serverAction") { + data[idx] = url[idx]; + } + } + var serverOptions = this.buildRequest(methods[url.serverAction], url); + if(serverOptions.method !== "PUT" && serverOptions.method !== "POST") { + data = ""; + } + Utils.request(serverOptions, JSON.stringify(data), config, function(result) { + if(callBackFunction) { + callBackFunction(result); + } + }); + }; + + this.infoDesign = function(url, callBackFunction) { + url.action = "_info"; + var designOptions = this.buildRequest(methods[url.action], url); + Utils.request(designOptions, "", config, function(result) { + if(callBackFunction) { + callBackFunction(result); + } + }); + }; + + this.queryDesign = function(url, callBackFunction) { + url.stringifyRequest = true; + var designOptions = this.buildRequest((url.request) ? "POST" : methods[url.action], url); + Utils.request(designOptions, JSON.stringify(url.request), config, function(result) { + if(callBackFunction) { + callBackFunction(result); + } + }); + }; + + this.buildRequest = function(method, url) { + if(!url.db && !url.serverAction) { + url.db = myDB; + } + + // dealing with the 'order feature' reported here: http://bit.ly/r1yipp + if(url && url.args && url.args.group_level && url.args.group) { + delete url.args.group; + } + + var qsparams = Utils.smartQueryString(url.args), reqOpts = Utils.clone(options); + + reqOpts.path += Utils.composeGetData(url); + reqOpts.method = method; + reqOpts.path = (qsparams === "") ? reqOpts.path : reqOpts.path + "?" + qsparams; + + if(method !== "GET") { + reqOpts.headers["Content-Type"] = "application/json"; + } + + if(mySession !== "") { + reqOpts.headers["Cookie"] = "AuthSession=" + mySession; + } + + reqOpts.headers["User-Agent"] = "PJsonCouch (node.js client for CouchDB) https://github.com/landeiro/PJsonCouch "; + + return reqOpts; + }; + } else { + return new PJsonCouch(options); + } }; - -module.exports = PJsonCouch; \ No newline at end of file + +module.exports = PJsonCouch; diff --git a/package.json b/package.json index 699fc0b..ae2c479 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "Pure-Json-on-Couch is a node.js client lib for CouchDB.", "tags": ["database", "couchdb"], "author": "Pedro Landeiro ", - "version": "0.1.0", + "version": "0.5.0", "main": "index", "repository": { "type": "git", diff --git a/testBasics.js b/testBasics.js index 44c9129..3fcf6f5 100644 --- a/testBasics.js +++ b/testBasics.js @@ -1,48 +1,54 @@ var PJsonCouch = require("./lib/PJsonCouch.js"); -log = function (desc,json) { +log = function(desc, json) { console.log(desc); console.log(json); } - // ** THESE TESTS WILL NOT WORK, THEY ARE JUST EXAMPLES // Examples of connections (the invocation of the constructor will not interact with the couchdb instance) -var test = PJsonCouch({protocol:"http",host:"127.0.0.1",port:5984}); -var test1 = PJsonCouch({protocol:"http",host:"mydomain.com",port:80}); +var test = PJsonCouch({ + host : "127.0.0.1", + port : 5984 +}); +var test1 = PJsonCouch({ + host : "mydomain.com", + port : 80 +}); // Can determine the databse in the constructor -var test2 = PJsonCouch({protocol:"http",host:"anotherdomain.com",port:5984,db:"mydatabase"}); +var test2 = PJsonCouch({ + host : "anotherdomain.com", + port : 5984, + db : "mydatabase" +}); // modify the default debug settings test.setDebugConfig({ - debug: true, /* allways show debug if true */ - debugOnError:true, /* only shows debug on error if true (this also will show debug if debug property is false) */ - debugWithHeaders: true, /* will include the reponseHeaders on debug if true */ - throwExceptionsOnError: false /* will throw exception instead of object error if true */ + debug : true, /* allways show debug if true */ + debugOnError : true, /* only shows debug on error if true (this also will show debug if debug property is false) */ + debugWithHeaders : true, /* will include the reponseHeaders on debug if true */ + throwExceptionsOnError : false /* will throw exception instead of object error if true */ }); - //Welcome msg -test.server({},function(r){log("welcome",r)}); - +test.server({}, function(r) {log("welcome", r) +}); //Can set the database -test.setDB({db:"mydatabase"}); +test.setDB({ + db : "mydatabase" +}); // How to know my database -log("My database",test.getDB()); - +log("My database", test.getDB()); // How to make login -test.login({user:"landeiro",password:"123"},function(r){ - log("my session hash",r) +test.login({ + user : "landeiro", + password : "123" +}, function(r) { + log("my session hash", r) //Another way to get my hash session - log("my session hash",test.getSession()); + log("my session hash", test.getSession()); // How to make logout - test.logout(function(r){log("logout",r);}); - + test.logout(function(r) {log("logout", r); + }); }); - - - - - - diff --git a/testDB.js b/testDB.js index c96a5f9..a60373d 100644 --- a/testDB.js +++ b/testDB.js @@ -1,56 +1,140 @@ var PJsonCouch = require("./lib/PJsonCouch.js"); var fs = require("fs"); - -log = function (desc,json) { +log = function(desc, json) { console.log(desc); console.log(json); } // connection without database definition -var test = PJsonCouch({protocol:"http",host:"127.0.0.1",port:5984}); +var test = PJsonCouch({ + host : "127.0.0.1", + port : 5984 +}); -var testWithDB = PJsonCouch({protocol:"http",host:"127.0.0.1",port:5984,db:"anotherDB"}); +var testWithDB = PJsonCouch({ + host : "127.0.0.1", + port : 5984, + db : "anotherDB" +}); // set a DB, this does not have callbackfuntion -test.setDB({db:"thisisatempdb"}); -log("My current DB",test.getDB()); +test.setDB({ + db : "thisisatempdb" +}); +log("My current DB", test.getDB()); // hello world form couchdb :) //test.server({}, function(data) {log("hello world form couchdb",data)}); // modify the default debug settings test.setDebugConfig({ - debug: false, - debugOnError:true, - debugWithHeaders: true, - throwExceptionsOnError: false + debug : false, + debugOnError : true, + debugWithHeaders : true, + throwExceptionsOnError : false }); // Run first the testDocs.js for the code bellow to work // Remove login if your DB is not protected -test.login({user:"landeiro",password:"123"},function(r){ +test.login({ + user : "landeiro", + password : "123" +}, function(r) { // Get all docs from DB, supports all args and request data from original couchdb API - test.queryDB({action:"_all_docs", args:{descending:true,startkey:"objmyid6",endkey:"objmyid2"}}, function(r){log("*queryDB start/endkey*",r);}); - test.queryDB({action:"_all_docs", request:{keys:["objmyid1","objmyid7"]}}, function(r){log("*queryDB keys*",r);}); + test.queryDB({ + action : "_all_docs", + args : { + descending : true, + startkey : "objmyid6", + endkey : "objmyid2" + } + }, function(r) {log("*queryDB start/endkey*", r); + }); + test.queryDB({ + action : "_all_docs", + request : { + keys : ["objmyid1", "objmyid7"] + } + }, function(r) { + log("*queryDB keys*", r); + }); // Get changes, supports all args from original couchdb API - test.queryDB({action:"_changes", args:{limit:5}}, function(r){log("*queryDB changes*",r);}); + test.queryDB({ + action : "_changes", + args : { + limit : 5 + } + }, function(r) { + log("*queryDB changes*", r); + }); + // Ensure full commit, - test.queryDB({action:"_ensure_full_commit"},function(r){ log("*queryDB full commit*",r); }); - // Get changes, supports all requests data from original couchdb API - test.queryDB({action:"_purge",request:{objmyid1:["1-23202479633c2b380f79507a776743d5"]}},function(r){ log("*queryDB full commit*",r); }); + test.queryDB({ + action : "_ensure_full_commit" + }, function(r) { + log("*queryDB full commit*", r); + }); + + // Get changes, supports all requests data from original couchdb API + test.queryDB({ + action : "_purge", + request : { + objmyid1 : ["1-23202479633c2b380f79507a776743d5"] + } + }, function(r) { + log("*queryDB full commit*", r); + }); + // Get revs limit - test.queryDB({action:"_revs_limit"},function(r){ log("*queryDB revs limit*",r); }); + test.queryDB({ + action : "_revs_limit" + }, function(r) { + log("*queryDB revs limit*", r); + }); + // Get security settings for the DB - test.queryDB({action:"_security"},function(r){ log("*GET queryDB security*",r); }); + test.queryDB({ + action : "_security" + }, function(r) { + log("*GET queryDB security*", r); + }); + // Set security settings for the DB, supports all requests data from original couchdb API - test.queryDB({action:"_security",request:{readers:{roles:[],names:["landeiro"]}}},function(r){ log("*SET queryDB security*",r); }); + test.queryDB({ + action : "_security", + request : { + readers : { + roles : [], + names : ["landeiro"] + } + } + }, function(r) { + log("*SET queryDB security*", r); + }); + // Executes a temporary view on the DB, supports all requests data from original couchdb API - test.queryDB({action:"_temp_view",request:{map : "function(doc) { if (doc.a > 6) { emit(null, doc.value); } }"}},function (r) {log("*temp view*",r)}); + test.queryDB({ + action : "_temp_view", + request : { + map : "function(doc) { if (doc.a > 6) { emit(null, doc.value); } }" + } + }, function(r) { + log("*temp view*", r) + }); + // Performs view cleanup - test.queryDB({action:"_view_cleanup"},function (r) {log("*view cleanup*",r)}); + test.queryDB({ + action : "_view_cleanup" + }, function(r) { + log("*view cleanup*", r) + }); + // Compact the DB - test.queryDB({action:"_compact"},function (r) {log("*compact BD*",r)}); - + test.queryDB({ + action : "_compact" + }, function(r) { + log("*compact BD*", r) + }); // Remove this if your DB is not protected }); diff --git a/testDesign.js b/testDesign.js index dd2d1de..064139a 100644 --- a/testDesign.js +++ b/testDesign.js @@ -1,56 +1,138 @@ var PJsonCouch = require("./lib/PJsonCouch.js"); var fs = require("fs"); - -log = function (desc,json) { - console.log(desc); - console.log(json); +log = function(desc, json) { + console.log(desc); + console.log(json); } // connection without database definition -var test = PJsonCouch({protocol:"http",host:"127.0.0.1",port:5984}); +var test = PJsonCouch({ + host : "127.0.0.1", + port : 5984 +}); // set a DB, this does not have callbackfuntion -test.setDB({db:"thisisatempdb"}); +test.setDB({ + db : "thisisatempdb" +}); // hello world form couchdb :) //test.server({}, function(data) {log("hello world form couchdb",data)}); // modify the default debug settings test.setDebugConfig({ - debug: true, - debugWithHeaders: true, - debugOnError:true, - throwExceptionsOnError: false - }); + debug : true, + debugWithHeaders : true, + debugOnError : true, + throwExceptionsOnError : false +}); // *** THESE TESTS WILL NOT WORK, THEY ARE JUST EXAMPLES // Get the design doc -test.queryDesign({design:"design_doc"},function (r) {log("*get the design doc*",r);}); +test.queryDesign({ + design : "design_doc" +}, function(r) { + log("*get the design doc*", r); +}); // Get info of the design doc -test.infoDesign({design:"design_doc"},function (r) {log("*get info of design doc*",r);}); - +test.infoDesign({ + design : "design_doc" +}, function(r) { + log("*get info of design doc*", r); +}); // ** Examples of Lists, supports all arguments and request data from original couchdb API // List customers using view by_name -test.queryDesign({design:"design_doc",list:"customers",view:"by_name"},function (r) {log("*get list with view*",r);}); +test.queryDesign({ + design : "design_doc", + list : "customers", + view : "by_name" +}, function(r) { + log("*get list with view*", r); +}); // List customers using view by_name from "Jane" to "Pedro" -test.queryDesign({design:"design_doc",list:"customers",view:"by_name",args:{startkey:"Jane",endkey:"Pedro"}},function (r) {log("*get list with view with args*",r);}); +test.queryDesign({ + design : "design_doc", + list : "customers", + view : "by_name", + args : { + startkey : "Jane", + endkey : "Pedro" + } +}, function(r) { + log("*get list with view with args*", r); +}); // List customers using view by_name with key "Jane", using request -test.queryDesign({design:"design_doc",list:"customers",view:"by_name",request:{keys:["Jane"]}},function (r) {log("*get list with view with request*",r);}) +test.queryDesign({ + design : "design_doc", + list : "customers", + view : "by_name", + request : { + keys : ["Jane"] + } +}, function(r) {log("*get list with view with request*", r); +}) // List customers using view by_name with keys ["joey","John Doe","Jane"], limited to 2 results -test.queryDesign({design:"design_doc",list:"customers",view:"by_name",args:{limit:2},request:{keys:["joey","John Doe","Jane"]}},function (r) {log("*get list with view with request and args*",r);}) - +test.queryDesign({ + design : "design_doc", + list : "customers", + view : "by_name", + args : { + limit : 2 + }, + request : { + keys : ["joey", "John Doe", "Jane"] + } +}, function(r) {log("*get list with view with request and args*", r); +}) // Display a Doc using Show costumer, supports all arguments from original couchdb API -test.queryDesign({design:"design_doc",show:"customer",id:"3535e007bd9c765de0554c0a4900385b"},function (r) {log("*get show*",r);}); - - -// ** Views, supports all arguments and request data from original couchdb API +test.queryDesign({ + design : "design_doc", + show : "customer", + id : "3535e007bd9c765de0554c0a4900385b" +}, function(r) { + log("*get show*", r); +}); +// ** Views, supports all arguments and request data from original couchdb API // Getting docs using view by_name with args reduce=false and key="Jane" -test.queryDesign({design:"design_doc",view:"by_name",args:{reduce:false,key:"Jane"}},function (r) {log("*get view with args*",r);}); +test.queryDesign({ + design : "design_doc", + view : "by_name", + args : { + reduce : false, + key : "Jane" + } +}, function(r) {log("*get view with args*", r); +}); // Getting docs using view by_name with request keys ["Jane"] -test.queryDesign({design:"design_doc",view:"by_name",request:{keys:["Jane"]}},function (r) {log("*get view with request*",r);}); -// Getting docs using view by_name with request keys ["Jane"] and argument limit=1 -test.queryDesign({design:"design_doc",view:"by_name",args:{limit:1},request:{keys:["Jane","joey"]}},function (r) {log("*get view with request and args*",r);}); +test.queryDesign({ + design : "design_doc", + view : "by_name", + request : { + keys : ["Jane"] + } +}, function(r) { + log("*get view with request*", r); +}); +// Getting docs using view by_name with request keys ["Jane"] and argument limit=1 +test.queryDesign({ + design : "design_doc", + view : "by_name", + args : { + limit : 1 + }, + request : { + keys : ["Jane", "joey"] + } +}, function(r) {log("*get view with request and args*", r); +}); // Getting docs using view by_type_name with startkey and endkey with array type -test.queryDesign({design:"design_doc",view:"by_type_name",args:{startkey:["customer","Jane"],endkey:["customer","joey"]}},function (r) {log("*get view and args*",r);}); - - +test.queryDesign({ + design : "design_doc", + view : "by_type_name", + args : { + startkey : ["customer", "Jane"], + endkey : ["customer", "joey"] + } +}, function(r) { + log("*get view and args*", r); +}); diff --git a/testDocs.js b/testDocs.js index 5a865a4..14d6826 100644 --- a/testDocs.js +++ b/testDocs.js @@ -1,144 +1,273 @@ var PJsonCouch = require("./lib/PJsonCouch.js"); var fs = require("fs"); - -log = function (desc,json) { +log = function(desc, json) { console.log(desc); console.log(json); } // connection without database definition -var test = PJsonCouch({protocol:"http",host:"127.0.0.1",port:5984}); +var test = PJsonCouch({ + host : "127.0.0.1", + port : 5984 +}); // modify the default debug settings test.setDebugConfig({ - debug: false, - debugOnError:true, - debugWithHeaders: true, - throwExceptionsOnError: false + debug : false, + debugOnError : true, + debugWithHeaders : true, + throwExceptionsOnError : false }); -// Attenion: I will delete and create this db for tests -var dbForTest = "mytempdblandeiro123"; +// Attenion: I will delete and create this db for tests +var dbForTest = "mytempdblandeiro123"; // Docs for test -var docs = [{_id:"objmyid0",a:0},{_id:"objmyid1",a:1},{_id:"objmyid2",a:3},{_id:"objmyid4",a:4},{_id:"objmyid5",a:5},{_id:"objmyid6",a:6},{_id:"objmyid7",a:7}]; +var docs = [{ + _id : "objmyid0", + a : 0 +}, { + _id : "objmyid1", + a : 1 +}, { + _id : "objmyid2", + a : 3 +}, { + _id : "objmyid4", + a : 4 +}, { + _id : "objmyid5", + a : 5 +}, { + _id : "objmyid6", + a : 6 +}, { + _id : "objmyid7", + a : 7 +}]; // Remove login if your DB is not protected -test.login({user:"landeiro",password:"123"},function(r){ - test.queryDB({db:dbForTest}, function(r){ - if (r.error === "not_found") - proceedWithTests(); - else - test.deleteDB({db:dbForTest},function (r) {if (r.ok) proceedWithTests();}) +test.login({ + user : "landeiro", + password : "123" +}, function(r) { + test.queryDB({ + db : dbForTest + }, function(r) { + if(r.error === "not_found") + proceedWithTests(); + else + test.deleteDB({ + db : dbForTest + }, function(r) { + if(r.ok) + proceedWithTests(); + }) }); }); - // Will create DB, save Bulks docs, get a Doc and delete it. function proceedWithTests() { - test.createDB({db:dbForTest},function () { - test.setDB({db:dbForTest}); - // Save bulk, supports all request data from original couchdb API - test.saveBulkDocs({docs:docs},function(r){ - log("insert bulk",r); - // Get Doc, supports all arguments from original couchdb API - test.getDoc({id:"objmyid0"},function (gdoc) { - log("*get doc*",gdoc) - if (!gdoc.error) { - // Delete a Doc, supports all arguments from original couchdb API - test.deleteDoc({doc:gdoc}, function (r) { log("*deleted "+gdoc._id+"*",r); saveDocsTests(); }); + test.createDB({ + db : dbForTest + }, function() { + test.setDB({ + db : dbForTest + }); + // Save bulk, supports all request data from original couchdb API + test.saveBulkDocs({ + docs : docs + }, function(r) { + log("insert bulk", r); + // Get Doc, supports all arguments from original couchdb API + test.getDoc({ + id : "objmyid0" + }, function(gdoc) { + log("*get doc*", gdoc) + if(!gdoc.error) { + // Delete a Doc, supports all arguments from original couchdb API + test.deleteDoc({ + doc : gdoc + }, function(r) { + log("*deleted " + gdoc._id + "*", r); + saveDocsTests(); + }); } }); }); }); - } // will save, update, info and copy docs, function saveDocsTests() { - //Saving a Doc, supports all arguments from original couchdb API - test.saveDoc({doc:{name:"pedro",surname:"landeiro"}},function (r) {log("*save doc withoutid*",r);}); - test.saveDoc({doc:{"_id": "myownid","name": "pedro","surname": "landeiro"}},function (r) { - log("*save doc with id*",r); - test.getDoc({id:"myownid"},function (gDoc) { + //Saving a Doc, supports all arguments from original couchdb API + test.saveDoc({ + doc : { + name : "pedro", + surname : "landeiro" + } + }, function(r) { + log("*save doc withoutid*", r); + }); + test.saveDoc({ + doc : { + "_id" : "myownid", + "name" : "pedro", + "surname" : "landeiro" + } + }, function(r) { + log("*save doc with id*", r); + test.getDoc({ + id : "myownid" + }, function(gDoc) { //Updating a existing doc gDoc.newfield = "this is a new field"; // will save doc with the new field - test.saveDoc({doc:gDoc},function (r) { - log("*updated doc "+gDoc._id+"*",r); - // Copy Doc, supports all arguments and request data from original couchdb API - test.copyDoc({source:{id:"myownid",rev:r._rev},destination:{id:"copied_doc"}}, function (r){ - log("*copied updated doc with id copied_doc",r); - //Info Docs, supports all arguments from original couchdb API - test.infoDoc({id:"copied_doc"}, function (r){log("*info from previous copied doc*",r); localDocsTests()}); + test.saveDoc({ + doc : gDoc + }, function(r) { + log("*updated doc " + gDoc._id + "*", r); + // Copy Doc, supports all arguments and request data from original couchdb API + test.copyDoc({ + source : { + id : "myownid", + rev : r._rev + }, + destination : { + id : "copied_doc" + } + }, function(r) { + log("*copied updated doc with id copied_doc", r); + //Info Docs, supports all arguments from original couchdb API + test.infoDoc({ + id : "copied_doc" + }, function(r) { + log("*info from previous copied doc*", r); + localDocsTests() + }); }) - }); }); - }); } // will save, update, info and copy docs locally, function localDocsTests() { console.log("LOCAL DOCS"); - //Saving a Doc, supports all arguments from original couchdb API - test.saveDoc({doc:{_id: "myownidlocal","name": "pedro","surname": "landeiro"},local:true},function (r) { - log("*save doc with id*",r); - test.getDoc({id:"myownidlocal",local:true},function (gDoc) { + //Saving a Doc, supports all arguments from original couchdb API + test.saveDoc({ + doc : { + _id : "myownidlocal", + "name" : "pedro", + "surname" : "landeiro" + }, + local : true + }, function(r) { + log("*save doc with id*", r); + test.getDoc({ + id : "myownidlocal", + local : true + }, function(gDoc) { //Updating a existing doc gDoc.newfield = "this is a new field in local doc"; // will save doc with the new field - test.saveDoc({doc:gDoc,local:true},function (r) { - log("*updated doc "+gDoc._id+"*",r); - // Copy Doc, supports all arguments and request data from original couchdb API - test.copyDoc({source:{id:r.id,rev:r.rev},destination:{id:"copied_doc_local"},local:true}, function (r){ - log("*copied updated doc with id copied_doc_local",r); - //Info Docs, supports all arguments from original couchdb API - test.infoDoc({id:"copied_doc_local",local:true}, function (r){log("*info from previous copied doc*",r);attachmentsTests()}); + test.saveDoc({ + doc : gDoc, + local : true + }, function(r) { + log("*updated doc " + gDoc._id + "*", r); + // Copy Doc, supports all arguments and request data from original couchdb API + test.copyDoc({ + source : { + id : r.id, + rev : r.rev + }, + destination : { + id : "copied_doc_local" + }, + local : true + }, function(r) { + log("*copied updated doc with id copied_doc_local", r); + //Info Docs, supports all arguments from original couchdb API + test.infoDoc({ + id : "copied_doc_local", + local : true + }, function(r) {log("*info from previous copied doc*", r); + attachmentsTests() + }); }) }); }); - }); - } function attachmentsTests() { // How to attach a binary file - test.getDoc({id:"myownid"},function (r) { + test.getDoc({ + id : "myownid" + }, function(r) { // *** Insert here a image file to upload *** - fs.readFile('couchdb.png','binary', function (err, data) { - if (err) throw err; + fs.readFile('couchdb.png', 'binary', function(err, data) { + if(err) + throw err; // Save a binary attachment on myownid Doc - test.saveDocAttachment({id:r._id,rev:r._rev, - attachment:{file:"image.png",content:data,content_type:"image/png",content_encoding:"binary"}},function (r) { - log("*insert image.png on myownid Doc*",r) - // How to attach text content (utf-8 is the default encoding) - test.saveDocAttachment({id:r.id,rev:r.rev, - attachment:{file:"file.txt",content:"some text",content_type:"text/plain"}},function (r) { - log("*insert file.txt on myownid Doc*",r); - }); - // Get a Binary content from image file (this content is available on property 'not_json') - test.getDocAttachment({id:r.id,attachment:{file:"image.png",content_encoding:"binary"}},function (r) { - log("*get image.png*",r); - }); - }); + test.saveDocAttachment({ + id : r._id, + rev : r._rev, + attachment : { + file : "image.png", + content : data, + content_type : "image/png", + content_encoding : "binary" + } + }, function(r) { + log("*insert image.png on myownid Doc*", r) + test.saveDocAttachment({ + id : r.id, + rev : r.rev, + attachment : { + file : "file.txt", + content : "some text", + content_type : "text/plain" + } + }, function(r) { + log("*insert file.txt on myownid Doc*", r); }); - }); - - - test.getDoc({id:"objmyid1"},function (r) { - test.saveDocAttachment({id:r._id,rev:r._rev, - attachment:{file:"fileToDelete.txt",content:"some text that will be deleted",content_type:"text/plain"}},function (r) { - log("*insert fileToDelete.txt on objmyid1 Doc*",r); - test.deleteDocAttachment({id:r.id,rev:r.rev,attachment:{file:"fileToDelete.txt"}}, function (r) { - log("*delete fileToDelete.txt on objmyid1 Doc*",r); - }) - }); + // Get a Binary content from image file (this content is available on property 'not_json') + test.getDocAttachment({ + id : r.id, + attachment : { + file : "image.png", + content_encoding : "binary" + } + }, function(r) { + log("*get image.png*", r); }); + }); + }); + }); - + test.getDoc({ + id : "objmyid1" + }, function(r) { + test.saveDocAttachment({ + id : r._id, + rev : r._rev, + attachment : { + file : "fileToDelete.txt", + content : "some text that will be deleted", + content_type : "text/plain" } - - - + }, function(r) { + log("*insert fileToDelete.txt on objmyid1 Doc*", r); + test.deleteDocAttachment({ + id : r.id, + rev : r.rev, + attachment : { + file : "fileToDelete.txt" + } + }, function(r) { + log("*delete fileToDelete.txt on objmyid1 Doc*", r); + }) + }); + }); +} \ No newline at end of file diff --git a/testGeo.js b/testGeo.js new file mode 100644 index 0000000..30ca2c1 --- /dev/null +++ b/testGeo.js @@ -0,0 +1,88 @@ +var PJsonCouch = require("./lib/PJsonCouch.js"); + +// connection without database definition +var test = PJsonCouch({ + host : "127.0.0.1", + port:5984 +}); + +// These are the same examples of GeoCouch github page: https://github.com/couchbase/geocouch + +// modify the default debug settings +test.setDebugConfig({ + debug : false, + debugOnError : true, + debugWithHeaders : true, + throwExceptionsOnError : false +}); + + +// Make a bounding box request +test.queryDesign({ + db : "places", + design : "main", + spatial : "points", + args : { + bbox : "0,0,180,90" + } +}, function(data) { + console.log(data); +}); + + +// Bounding box search and the date line +test.queryDesign({ + db : "places", + design : "main", + spatial : "points", + args : { + bbox : "110,-60,-30,15", + plane_bounds:"-180,-90,180,90" + } +}, function(data) { + console.log(data.rows); +}); + + +// List function support +test.queryDesign({ + db : "places", + design : "main", + spatial : "points", + list:"wkt", + args : { + bbox : "-180,-90,180,90" + } +}, function(data) { + console.log(data); +}); + + +// Compaction +test.queryDesign({ + db : "places", + design : "main", + spatial : "points", + action:"_compact" +}, function(data) { + console.log(data); +}); + + +// Info +test.queryDesign({ + db : "places", + design : "main", + spatial : "points", + action:"_info" +}, function(data) { + console.log(data); +}); + +// Cleanup +test.queryDB({ + db : "places", + action:"_spatial_cleanup", +}, function(data) { + console.log(data); +}); \ No newline at end of file diff --git a/testServer.js b/testServer.js index 921240b..2213585 100644 --- a/testServer.js +++ b/testServer.js @@ -1,44 +1,83 @@ var PJsonCouch = require("./lib/PJsonCouch.js"); - -log = function (desc,json) { +log = function(desc, json) { console.log(desc); console.log(json); } - // connection without database definition -var test = PJsonCouch({protocol:"http",host:"127.0.0.1",port:5984}); - +var test = PJsonCouch({ + host : "127.0.0.1", + port : 5984 +}); // modify the default debug settings test.setDebugConfig({ - debug: false, - debugOnError:true, - debugWithHeaders: false, - throwExceptionsOnError: false + debug : false, + debugOnError : true, + debugWithHeaders : false, + throwExceptionsOnError : false }); - // Remove login if your DB is not protected -test.login({user:"landeiro",password:"123"},function(r){ +test.login({ + user : "landeiro", + password : "123" +}, function(r) { // Welcome msg from CouchDB - test.server({},function (r) {log("*welcome msg*",r);}); + test.server({}, function(r) { + log("*welcome msg*", r); + }); // Show active tasks - test.server({action:"_active_tasks"},function (r) {log("*active tasks*",r);}); + test.server({ + action : "_active_tasks" + }, function(r) { + log("*active tasks*", r); + }); // Start continuos replication database. Replication supports all configuration from original couchdb API - test.server({action:"_replicate",source:"thisisatempdb",target:"http://somedomain.com/land",continuous:true},function (r) { - log("*replicate*",r); - // Cancel continuos replication database, supports all configuration from original couchdb API - test.server({action:"_replicate",source:"thisisatempdb",target:"http://somedomain.com/land",continuous:true,cancel:true},function (r) {log("*cancel replication*",r);}) + test.server({ + action : "_replicate", + source : "thisisatempdb", + target : "http://somedomain.com/land", + continuous : true + }, function(r) { + log("*replicate*", r); + // Cancel continuos replication database, supports all configuration from original couchdb API + test.server({ + action : "_replicate", + source : "thisisatempdb", + target : "http://somedomain.com/land", + continuous : true, + cancel : true + }, function(r) { + log("*cancel replication*", r); + }) }); // Show all database in couchdb instance - test.server({action:"_all_dbs"},function (r) {log("*all bds*",r);}); + test.server({ + action : "_all_dbs" + }, function(r) { + log("*all bds*", r); + }); // Shows log on the not_json property, supports all args from original couchdb API - test.server({action:"_log",args:{bytes:2000}},function (r) {log("*log*",r);}); + test.server({ + action : "_log", + args : { + bytes : 2000 + } + }, function(r) { + log("*log*", r); + }); // Shows stats, supports all args from original couchdb API - test.server({action:"_stats"},function (r) {log("*stats*",r);}); + test.server({ + action : "_stats" + }, function(r) { + log("*stats*", r); + }); // Gets a new uuid, supports all args from original couchdb API - test.server({action:"_uuids"},function (r) {log("*uuids*",r);}); - + test.server({ + action : "_uuids" + }, function(r) { + log("*uuids*", r); + }); });