1 /* appjet:version 0.1 */
  2 
  3 /* appjet:library */
  4 
  5 import("lib-json");
  6 import("lib-restclient");
  7 
  8 /*
  9  Copyright (C) 2007 Damien Katz <damien_katz@yahoo.com>.
 10  Copyright (C) 2010 by JGate, H. Schroeder
 11 
 12  This file is licenced under a Creative Commons Attribution 3.0 Unported
 13  Licence <http://creativecommons.org/licenses/by/3.0/>.
 14 */
 15 
 16 /**
 17  * @fileOverview A simple class to represent a CouchDB client connection.
 18  * It requires appjet.jar 1.0.4 or higher for methods other than GET
 19  */
 20 
 21 /**
 22  * The CouchDB class represents the client connection to the CouchDB. It encapsulates
 23  * a rest client, that talks to the databse using a RESTful API. The class uses
 24  * several defaults. For normal operation just the first parameter with the
 25  * database name is needed. The necessary authentication is done by the framework. 
 26  *
 27  * @constructor
 28  * @class The CouchDB class represents the client connection to the CouchDB.
 29  * @param {string} name  the name of the database to talk to
 30  * @param {string} [host] the couchdb host to talk to. Defaults to localhost
 31  * @param {integer} [port] the couchdb port to talk to. Defaults to 5984
 32  * @param {string} [user] the user name to login. Defaults to the database owner
 33  * @param {string} [password] the password to use. Defaults to the api key
 34  * @param {boolean} [allowUnauthorized] if true, the class does not use internal credentials
 35  */
 36 function CouchDB(name, host, port, user, password, allowUnauthorized)
 37 {
 38     this.name = name;
 39     this.host = host ? host : 'localhost';
 40     this.port = port ? port : 5984;
 41 
 42     this.url = this.host + ":" + this.port + "/" + encodeURIComponent(name) +"/";
 43 
 44     if (user != undefined && password != undefined)
 45     {
 46         this.url = user + ":" + password + "@" + this.url;
 47     }
 48     else if (allowUnauthorized != true)
 49     {
 50         // authenticate couchdb access
 51         var auth = appjet._native._credentials;
 52 
 53         if (auth != undefined)
 54         {
 55             this.url = auth[0] + ":" + auth[1] + "@" + this.url;
 56         }
 57     }
 58 
 59     var client = new RestClient();
 60 
 61     /** 
 62      * Returns the last response from the CouchDB. Useful to get a description in case
 63      * of an error.
 64      * @return {object} object with the communication details of the last call.
 65      */
 66     this.getLastResult = function()
 67     {
 68         return this.result;
 69     }
 70 
 71     /**
 72      * Returns the parsed function result or null in case of an error.
 73      * Use getLastResult for an error description. (Used internally)
 74      * @param {object} result the result object from the rest client.
 75      * @return {object} object with the communication details or null in case of an error.
 76      */
 77     this.getResult = function(result)
 78     {
 79         this.result = result;
 80 
 81         if (result.status >= 200 && result.status < 300)
 82             return JSON.parse(result.data);
 83         else
 84             return null;
 85     }
 86 
 87     /**
 88      * Creates a new CouchDB database. Used by the backend, not for general use.
 89      * @return {object} object with the communication details or null in case of an error.
 90      */    
 91     this.createDatabase = function()
 92     {
 93         return this.getResult(client.exec("PUT", this.url, {}));
 94     }
 95 
 96     /**
 97      * Deletes an existing CouchDB database. Used by the backend, not for general use.
 98      * @return {object} object with the communication details or null in case of an error.
 99      */    
100     this.deleteDatabase = function()
101     {
102         return this.getResult(client.exec("DELETE", this.url, {}));
103     }
104 
105     /**
106      * Returns information about the database.
107      * @return {object} object with the database details or null in case of an error.
108      */
109     this.info = function()
110     {
111         return this.getResult(client.exec("GET", this.url));
112     }
113 
114     /**
115      * Reads the document with the specified document id.
116      *
117      * @param {string} id the document id.
118      * @return {object} the document or null in case of an error.
119      */
120     this.readDoc = function(id)
121     {
122         return this.getResult(client.exec("GET", this.url + encodeURIComponent(id)));
123     }
124 
125     /**
126      * Writes a document to the database. On return the document has two additional
127      * attributes: the ID, and the revision
128      *
129      * @param {string} doc the document to store
130      * @return {object} the document or null in case of an error.
131      */
132     this.writeDoc = function(doc)
133     {
134         var result;
135 
136         if (doc._id == undefined)
137             result = this.getResult(client.exec("POST", this.url, doc));
138         else
139             result = this.getResult(client.exec("PUT", this.url + encodeURIComponent(doc._id), doc));
140 
141         // document stored, get id and rev
142         if (result != null)
143         {
144             doc._id = result.id;
145             doc._rev = result.rev;
146         }
147         return result;
148     }
149 
150     /**
151      * Deletes a document from the database.
152      *
153      * @param {object} doc the document to delete
154      * @return {object} the deleted document or null in case of an error.
155      */
156     this.deleteDoc = function(doc)
157     {
158         var result = this.getResult(client.exec("DELETE", this.url + encodeURIComponent(doc._id) + "?rev=" + doc._rev, doc));
159         // document deleted, get rev and mark deleted
160         if (result != null)
161         {
162             doc._deleted = true;
163             doc._rev = result.rev;
164         }
165         return result;
166     }
167 }
168 
169 /* appjet:server */
170 print(H2("lib-couchdb"));
171 print("A CouchDB client library for AppJet");