Coverage

92%
777
720
57

/Users/villa/dev/personal/projects/js/node-couchdb/lib/base.js

89%
59
53
6
LineHitsSource
11var _ = require('underscore');
21var debug = require('debug')('couchdb:general');
31var dbody = require('debug')('couchdb:body');
41var dreq = require('debug')('couchdb:request');
5
6
71require('buffer');
8
91module.exports = RequestBase;
10
111function RequestBase(options) {
12139 this.options = options || {};
13139 if (this.options.request) {
1461 this.request = this.options.request;
15 }
16
17139 this.options = _.defaults(this.options || {}, {
18 method: 'GET'
19 });
20
21139 this.enableJson = true;
22}
23
241['HEAD', 'GET', 'POST', 'DELETE', 'PUT', 'COPY'].forEach(function(method) {
256 RequestBase.prototype['_' + method.toLowerCase()] = function(url, options, callback) {
26231 if (typeof options == 'function') {
27175 callback = options;
28175 options = {};
29 }
30
31231 options.method = method;
32231 return this._request(url, options, callback);
33 };
34});
35
36
371RequestBase.prototype._request = function(url, options, callback) {
38248 var request = this.request || (this.request = require('request').defaults(this.options)),
39 opt = {
40 url: url
41 };
42
43
44248 if (this.options.auth) {
45133 opt.auth = {
46 user: this.options.auth.user,
47 pass: this.options.auth.pass,
48 sendImmediately: true
49 };
50 }
51
52
53248 if (typeof options == 'function') {
540 callback = options;
55248 } else if (typeof options === 'string') {
560 opt.method = options;
57 } else {
58248 _.extend(opt, options);
59 }
60
61248 if (typeof opt.strictSSL == 'boolean')
620 opt.rejectUnauthorized = opt.strictSSL;
63
64 // set headers
65248 opt.headers = (opt.headers && typeof(opt.headers) == 'object') ? opt.headers : {};
66
67
68 /* jshint sub: true */
69248 if (opt.headers['Accept'] || opt.headers['accept'] || this.enableJson)
70244 opt.headers["Accept"] = opt.headers["Accept"] || opt.headers["accept"] || "application/json";
71
72248 if (opt.headers['Content-Type'] || opt.headers['content-type'] || this.enableJson) {
73244 opt.headers["Content-Type"] = opt.headers["Content-Type"] || opt.headers["content-type"] || "application/json";
74 }
75
76 // prevent bugs where people set encoding when piping
77248 if (opt.encoding !== undefined && callback) {
780 opt.encoding = opt.encoding;
790 delete opt.headers['Content-Type'];
800 delete opt.headers['Accept'];
81 }
82
83248 if (opt.headers['Content-Type'] === 'multipart/related' && opt.method === 'GET') {
845 opt.encoding = null;
85 }
86
87248 dreq(JSON.stringify(opt));
88
89248 debug(opt.method.toUpperCase() + ':' + opt.url);
90248 return request(opt, function(err, res, body) {
91248 if (Buffer.isBuffer(body))
925 body = body.toString();
93
94248 dbody(typeof body == 'string' ? body : JSON.stringify(body));
95
96 // handle string if json option is off
97248 if (typeof body == 'string' && (!res.headers['content-type'] || /json/.test(res.headers['content-type']))) {
98237 try {
99237 body = JSON.parse(body);
100 } catch (e) {
1015 var contentType = res.headers && res.headers['content-type'];
1025 if (!contentType || contentType.indexOf('text/plain') == -1)
1035 debug('JSON parse error:', e);
104 }
105 }
106
107249 if (err) return (callback && callback(err, body, res));
108
109247 if (res.statusCode < 400) {
110239 callback && callback(err, body, res);
111 } else {
1128 body = body || {};
1138 body.statusCode = res.statusCode;
1148 callback && callback(body, null, res);
115 }
116 });
117};

/Users/villa/dev/personal/projects/js/node-couchdb/lib/config.js

100%
19
19
0
LineHitsSource
11var _ = require('underscore'),
2 util = require('util'),
3 RequestBase = require('./base');
4
51function Config(url, options) {
65 RequestBase.call(this, options);
75 this.configUrl = url.replace(/\/$/, '') + '/_config';
8}
9
101util.inherits(Config, RequestBase);
11
121_.extend(Config.prototype, {
13 all: function(callback) {
141 this._get(this.configUrl, function(err, cfgs) {
151 callback(err, cfgs);
16 });
17 },
18 section: function(section) {
191 var self = this;
201 return {
21 get: self.get.bind(self, section),
22 set: self.set.bind(self, section),
23 del: self.del.bind(self, section)
24 };
25 },
26 get: function(section, key, callback) {
273 this._get([this.configUrl, section, key].join('/'), function(err, val) {
283 if (err && err.statusCode == 404) {
29 // if the config key is not found, return undefined
301 return callback(null, undefined);
31 }
322 callback(err, val);
33 });
34 },
35 set: function(section, key, val, callback) {
362 this._put([this.configUrl, section, key].join('/'), {
37 body: JSON.stringify(val)
38 }, function(err, oldVal) {
392 callback(err, oldVal);
40 });
41 },
42 del: function(section, key, callback) {
431 this._delete([this.configUrl, section, key].join('/'), function(err, oldVal) {
441 callback(err, oldVal);
45 });
46 }
47});
48
49
50
511module.exports = Config;

/Users/villa/dev/personal/projects/js/node-couchdb/lib/couch.js

75%
116
88
28
LineHitsSource
11var assert = require('assert'),
2 crypto = require('crypto'),
3 events = require('events'),
4 _ = require('underscore'),
5 util = require('util'),
6 qs = require('querystring'),
7 path = require('path'),
8 Config = require('./config'),
9 Database = require('./db'),
10 RequestBase = require('./base');
11
12
131function CouchDB(url, options) {
1434 RequestBase.call(this, options);
1534 this.url = url.replace(/\/$/, '');
1634 this.bindedDBs = {};
17}
18
19
201util.inherits(CouchDB, RequestBase);
21
221_.extend(CouchDB.prototype, {
23 config: function(options) {
245 return new Config(this.url, options || this.options);
25 },
26 /**
27 * @param {string} dbname
28 * @param {Object=} options if no options is passed the Database will share the same options as CouchDB
29 */
30 database: function(dbname, options) {
3139 var db = new Database(this.url + '/' + dbname, dbname, options || this.options);
3239 db.newUuids = this.newUuids.bind(this);
3339 return db;
34 },
35 bind: function(dbname, options) {
3634 if (this[dbname] && !this.bindedDBs[dbname]) {
371 throw new Error('Invalid dbname for bind: ' + dbname);
38 }
39
4033 var db = this[dbname] = this.database(dbname, options || this.options);
41
4233 this.bindedDBs[dbname] = true;
4333 return this;
44 },
45 unbind: function(dbname) {
462 if (this.hasOwnProperty(dbname) && this.bindedDBs[dbname]) {
472 delete this[dbname];
482 delete this.bindedDBs[dbname];
49 }
502 return this;
51 },
52 existsDb: function(dbname, callback) {
53 // on avaliable for couchdb >= 1.5
540 return new Database(this.url, dbname, this.options).exists(callback);
55 },
56 auth: function(user, pass) {
5764 delete this.options.auth;
5864 this.options.headers && (delete this.options.headers.Authorization);
5964 if (user) {
6036 this.options.auth = {
61 user: user
62 };
63
6436 pass && (this.options.auth.pass = pass);
65 }
6664 return this;
67 },
68 /**
69 * read version information
70 * @param {function} callback
71 */
72 info: function(callback) {
7333 this._get(this.url, function(err, info, res) {
7433 callback(err, info);
75 });
76 },
77 /**
78 * @callback statCallback
79 * @param {Object} err
80 * @param {}
81 */
82 /**
83 * @param {string|number} statisticId
84 * @param {statCallback} callback
85 * @auth
86 */
87 stats: function(statisticId, callback) {
882 if (typeof statisticId == 'function' && callback === undefined) {
891 callback = statisticId;
901 statisticId = undefined;
91 }
92
932 this._get(this.url + '/_stats' + (statisticId ? ('/couchdb/' + statisticId) : ''),
94 function(err, stat, res) {
952 callback(err, stat);
96 });
97 },
98 /**
99 * List of running tasks
100 * @param {function} callback
101 * @auth
102 */
103 activeTasks: function(callback) {
1041 this._get(this.url + '/_active_tasks', function(err, tasks, res) {
1051 callback(err, tasks);
106 });
107 },
108 /**
109 * @param {function} callback
110 */
111 allDbs: function(callback) {
1122 this._get(this.url + '/_all_dbs', function(err, alldbs, res) {
1132 callback && callback(err, alldbs);
114 });
115 },
116 newUuids: function(n, callback) {
1173 var self = this;
1183 self.uuids_cache = self.uuids_cache || [];
119
1203 if (self.uuids_cache.length >= n) {
1212 var uuids = self.uuids_cache.slice(self.uuids_cache.length - n);
1222 if (self.uuids_cache.length - n === 0) {
1231 self.uuids_cache = [];
124 } else {
1251 self.uuids_cache =
126 self.uuids_cache.slice(0, self.uuids_cache.length - n);
127 }
1282 return callback(null, uuids);
129 } else {
130 // cache 100 ids for future usage
1311 this._get(this.url + "/_uuids?count=" + (100 + n), function(err, result) {
1321 if (err) return callback(err);
1331 var uuids = (result && result.uuids) || [];
1341 self.uuids_cache =
135 self.uuids_cache.concat(uuids.slice(0, 100));
136
1371 callback(err, uuids.slice(100));
138 });
139 }
140 },
141
142 /**
143 *
144 */
145 restart: function(callback) {
1460 this._post(this.url + '/_restart', function(err, body) {
1470 callback(err);
148 });
149 },
150 /**
151 * watch db updates events
152 *
153 * @param {number} timeout
154 * @couchdb 1.4
155 */
156 dbUpdates: function(timeout, callback) {
1570 if (arguments.length == 1) {
1580 if (typeof timeout == 'function') {
1590 callback = timeout;
1600 timeout = 0;
161 }
162 }
163
1640 var params = {};
165
1660 if (timeout)
1670 params.timeout = timeout;
168
1690 if (callback)
1700 params.feed = 'longpoll';
171 else
1720 params.feed = 'continuous';
173
1740 if (callback)
1750 this._get(this.url + '/_db_updates?' + qs.stringify(params), function(err, updates, res) {
1760 callback(err, updates);
177 });
178 else {
179 // TODO: publish continues event
1800 var bus = new events.EventEmitter();
1810 return bus;
182 }
183 },
184 /**
185 * @param {number} bytes
186 * @param {number} offset
187 * @parma {function} callback
188 */
189 log: function(bytes, offset, callback) {
1903 if (typeof offset == 'function' && callback === undefined) {
1911 callback = offset;
1921 offset = undefined;
1932 } else if (typeof bytes == 'function' && offset === undefined && callback === undefined) {
1941 callback = bytes;
1951 bytes = undefined;
196 }
197
1983 var query = {}, qstr;
1993 (bytes !== undefined) && (query.bytes = bytes);
2003 (offset !== undefined) && (query.offset = offset);
201
202
2033 var qstr = qs.stringify(query);
204
2053 this._get(this.url + '/_log?' + qstr, function(err, body) {
2063 callback && callback(err, body || '');
207 });
208 },
209 replicate: function(source, target, options, callback) {
2100 if (typeof options == 'function') {
2110 callbak = options;
2120 options = undefined;
213 }
214
2150 options = options || {};
216
2170 var body;
2180 try {
2190 body = JSON.stringify(_.extend({
220 source: soruce,
221 target: target
222 }, options));
223 } catch (e) {
2240 return (callback && callback(e));
225 }
226
2270 this._post(this.url + "/_replicate", {
228 body: body
229 },
230 function(err, body) {
2310 callback && callback(err, body);
232 });
233 },
234
235 /**
236 * @auth
237 */
238 allDesignDocs: function(callback) {
2391 var self = this;
2401 self.allDbs(function(err, dbs) {
2411 if (err) return (callback && callback(err));
2421 var ddocs = [];
2431 getDdocs();
244
2451 function getDdocs() {
2464 if (dbs.length) {
2473 var db = dbs.shift();
2483 self.database(db).allDesignDocs(function(err, data) {
2493 if (err) return callback(err);
2503 Array.prototype.push.apply(ddocs, data);
2513 getDdocs();
252 });
253 } else {
2541 callback && callback(undefined, ddocs);
255 }
256 }
257 });
258 },
259 // ========================
260 // Session Management
261 // ========================
262 login: function(username, passwd, callback) {
2636 if (!this.options.jar) {
2645 this.options.jar = this.__jar = require('request').jar();
265 }
2666 this._post(this.url + '/_session', {
267 body: JSON.stringify({
268 name: username,
269 password: passwd
270 })
271 }, function(err, body, res) {
2726 callback && callback(err, body);
273 });
274 },
275 logout: function(callback) {
2766 var self = this;
2776 this._delete(this.url + '/_session', function(err, body) {
2786 if (self.__jar === self.options.jar) {
2796 delete self.options.jar;
2806 delete self.__jar;
281 }
2826 callback && callback.bind(self)(err, body);
283 });
284 },
285 /**
286 * @callback sessionCallback
287 * @parm {object} err
288 * @param {object} info session information
289 */
290 /**
291 * @param {sessionCallback} callback
292 */
293 session: function(callback) {
2941 this._get(this.url + '/_session', function(err, body) {
2951 callback && callback(err, body);
296 });
297 }
298});
299
3001module.exports = CouchDB;

/Users/villa/dev/personal/projects/js/node-couchdb/lib/db.js

89%
222
199
23
LineHitsSource
11var _ = require('underscore');
21var util = require('util');
31var qs = require('querystring');
41var follow = require('follow');
5
61var Document = require('./doc'),
7 Local = require('./local'),
8 DesignDoc = require('./ddoc'),
9 RequestBase = require('./base'),
10 Executor = require('./exec');
11
121module.exports = Database;
13
14/**
15 * @param {string} url url that include dbname
16 * @param {string} dbname
17 * @param {Object=} options
18 */
191function Database(url, dbname, options) {
2042 options = options || {};
21
2242 if (!url || !dbname)
232 throw new Error('url, dbname must be provided');
24
2540 RequestBase.call(this, options);
2640 this.url = url.replace(/\/$/, '');
2740 this.dbname = dbname;
28}
29
301util.inherits(Database, RequestBase);
31
321_.extend(Database.prototype, {
33 /*
34 * Extend Database object
35 * @param {Object} extend
36 */
37 extend: function(extend) {
381 for (var key in extend) {
392 var val = extend[key];
402 if (typeof val == 'function') {
411 this[key] = val.bind(this);
42 } else
431 this[key] = val;
44 }
451 return this;
46 },
47 doc: function(doc, options) {
4828 return new Document(this.url, doc, options || this.options);
49 },
50 insert: function(doc, options, callback) {
513 if (typeof options == 'function') {
522 callback = options;
532 options = undefined;
54 }
55
56
573 if (typeof options == 'string') {
581 doc._id = options;
591 options = undefined;
60 }
61
623 var doc = this.doc(doc, options);
633 doc.create(callback);
64 },
65 fetch: function(id, callback) {
661 this.doc(id).open(callback);
67 },
68 mfetch: function(ids, callback) {
691 this.searchByKeys(ids, {
70 include_docs: true
71 }, callback);
72 },
73 local: function(options) {
741 return new Local(this.url, options || this.options);
75 },
76 design: function(designName, options) {
7719 return new DesignDoc(this.url, designName, options || this.options);
78 },
79 designDoc: function() {
801 return this.design.apply(this, arguments);
81 },
82 view: function(design, view, options) {
838 if (typeof view != 'string') {
848 options = view;
858 var dv = design.split('/');
868 design = dv[0];
878 view = dv[1];
88 }
898 return this.design(design, options || this.options).view(view);
90 },
91 newUuids: function() {
921 throw new Error('No newUuids method in Database');
93 },
94 /**
95 * @couchdb 1.5
96 */
97 exists: function(callback) {
980 this._head(this.url, function(err, body, res) {
990 if (err && err.statusCode == 404)
1000 return callback(null, false);
101
1020 callback(err, !err, body);
103 });
104 },
105 info: function(callback) {
1063 this._get(this.url, function(err, info) {
1073 callback(err, info);
108 });
109 },
110 create: function(callback) {
11133 this._put(this.url, function(err, body) {
11233 if (body && body.error) {
1130 callback && callback(err || body.reason);
114 } else
11533 callback && callback(err, body);
116 });
117 },
118 destroy: function(callback) {
11934 this._delete(this.url, callback);
120 },
121 purge: function(docs, callback) {
1221 var body;
1231 try {
1241 body = JSON.stringify(docs || {});
125 } catch (e) {
1260 return (callback && callback(e));
127 }
128 // TODO: format docs obj
1291 this._post(this.url + '/_purge', {
130 body: body
131 }, function(err, body) {
1321 callback && callback(err, body);
133 });
134 },
135 compact: function(callback) {
1360 this._post(this.url + '/_compact', callback);
137 },
138 compactDdoc: function(ddoc, callback) {
1390 this._post(this.url + '/_compact/' + ddoc, callback);
140 },
141 ensureCommit: function(callback) {
1421 this._post(this.url + '/_ensure_full_commit', callback);
143 },
144 viewCleanup: function(callback) {
1451 this._post(this.url + '/_view_cleanup', callback);
146 },
147 /**
148 * @param {number} skip
149 * @param {number} limit
150 * @param {AllDocsOptions=} options
151 * @param {function} callback
152 */
153 allDocs: function(skip, limit, options, callback) {
1544 var query = this.select();
1554 if (arguments.length === 0) {
1561 return query;
1573 } else if (arguments.length == 1) {
1581 callback = skip;
1591 skip = limit = undefined;
1602 } else if (arguments.length == 2 && typeof limit == 'function') {
1611 callback = limit;
1621 options = skip;
1631 skip = limit = undefined;
1641 } else if (arguments.length == 3 && typeof options == 'function') {
1651 callback = options;
1661 options = undefined;
167 }
168
169
1703 (typeof skip == 'number') && query.skip(skip);
1713 (typeof limit == 'number') && query.limit(limit);
172
1733 if (options)
1741 query.set(options);
175
1763 query.execute(callback);
177 },
178 /**
179 * @name AllDocsOptions
180 * @class
181 * @property {boolean} inclusive_end
182 * @property {boolean} include_docs whether include the full doc, default is false
183 * @property {boolean} descending
184 * @property {boolean} group
185 * @property {number} group_level
186 * @property {boolean} reduce
187 * @property {number} skip
188 * @property {number} limit
189 */
190 /*
191 * @param {string} startkey|keys
192 * @param {string=} endkey
193 * @param {AllDocsOptions=} options
194 * @param {function} callback
195 */
196 searchByKeys: function(startkey, endkey, options, callback) {
1979 var key, keys;
1989 if (arguments.length == 2 && typeof endkey == 'function') {
1992 callback = endkey;
2002 if (startkey instanceof Array) {
2011 keys = startkey;
202 } else {
2031 key = startkey;
204 }
2052 endkey = startkey = undefined;
2067 } else if (arguments.length == 3 && typeof options == 'function') {
2077 callback = options;
2087 options = undefined;
2097 if (typeof endkey != 'string') {
2102 options = endkey;
2112 if (startkey instanceof Array) {
2121 keys = startkey;
213 } else {
2141 key = startkey;
215 }
216 }
217 }
218
2199 var query = this.select();
2209 if (!keys) {
2217 key && query.key(key);
2227 query.startkey(startkey || undefined).endkey(endkey || undefined).set(options).execute(callback);
223 } else {
2242 query.keys(keys).set(options).execute(callback);
225 }
226 },
227 /**
228 * @param {string} startid
229 * @param {string} endId
230 * @param {AllDocsOptions=} options
231 * @param {function} callback
232 */
233 searchByIds: function(startId, endId, options, callback) {
2343 if (arguments.length == 2 && typeof endId == 'function') {
2351 callback = endId;
2361 endId = startId;
2372 } else if (arguments.length == 3 && typeof options == 'function') {
2382 callback = options;
239
2402 if (typeof endId == 'string') {
2411 options = undefined;
242 } else {
2431 options = endId;
2441 endId = startId;
245 }
246 }
247
2483 this.select().betweenIds(startId || undefined, endId || undefined).set(options).execute(callback);
249 },
250 /**
251 *
252 */
253 select: function(options) {
25417 var self = this,
255 executor = new Executor(Database.prototype.select.additions, 'skip', 'limit', 'descending', 'endkey', 'startkey', 'endkey_docid', 'startkey_docid',
256 'group', 'group_level', 'include_docs', 'inclusive_end', 'key', 'reduce', 'stale', 'keys');
25717 executor.execute = function(callback) {
25817 var opts = _.clone(this.options);
259
26017 try {
26117 ['startkey', 'endkey', 'key'].forEach(function(p) {
26251 opts[p] && (opts[p] = JSON.stringify(opts[p]));
263 });
264 } catch (e) {
2650 return (callback && callback(e));
266 }
267
26817 if (opts.keys && opts.keys.length) {
2692 var keys = opts.keys,
270 body, qstr = '';
2712 delete opts.keys;
272
273
2742 try {
2752 body = JSON.stringify({
276 keys: keys
277 });
278 } catch (e) {
2790 e.oldMessage = e.message;
2800 e.message = "'keys' parameter is invalid JSON.";
2810 return (callback && callback(e));
282 }
283
2842 var qstr = qs.stringify(opts);
285
2862 self._post(self.url + '/_all_docs?' + qstr, {
287 body: body
288 }, function(err, body) {
2892 if (err) return callback(err);
2902 callback && callback(err, body.rows, body.total_rows, body.offset, body);
291 });
292 } else {
29315 var qstr = qs.stringify(opts);
294
29515 self._get(self.url + '/_all_docs?' + qstr, function(err, body) {
29615 if (err) return callback(err);
29715 callback && callback(err, body.rows, body.total_rows, body.offset, body.update_seq, body);
298 });
299 }
300 };
301
30217 executor.betweenKeys = function(startkey, endkey) {
3031 this.options.startkey = startkey;
3041 this.options.endkey = endkey;
3051 return this;
306 };
307
30817 executor.betweenIds = function(startid, endid) {
3093 this.options.startkey_docid = startid;
3103 this.options.endkey_docid = endid;
3113 return this;
312 };
313
31417 if (options)
3150 executor.set(options);
316
31717 return executor;
318 },
319 /**
320 * Get tempView result with given mapFn and reduceFn
321 *
322 * @param {function} mapFn map function for tempView
323 * @param {function} reduceFn reduce function for tempView
324 * @param {Object=} options
325 * @param {function=} callback function called after response
326 */
327 tempView: function(mapFn, reduceFn, options, callback) {
3281 if (arguments.length === 3) {
3291 callback = options;
3301 options = undefined;
331 }
332
3331 var body = {
334 language: "javascript"
335 };
336
337
3381 if (typeof(mapFn) != "string")
3391 mapFn = "(" + mapFn.toString() + ")";
340
3411 body.map = mapFn;
342
3431 if (reduceFn) {
3441 if (typeof(reduceFn) != "string")
3450 reduceFn = "(" + reduceFn.toString() + ")";
3461 body.reduce = reduceFn;
347 }
348
3491 var qstr = '';
350
3511 try {
3521 body = JSON.stringify(body);
353 } catch (e) {
3540 return (callback && callback(e));
355 }
356
3571 var qstr = qs.stringify(options);
358
3591 this._post(this.url + "/_temp_view?" + qstr, {
360 body: body
361 }, function(err, body) {
3621 callback && callback(err, body);
363 });
364 },
365
366 /**
367 * Save a document to database, if doc have no revision, then create a new document.
368 * @param {string} docid
369 * @param {Object} doc
370 * @param {Object=} options
371 * @param {function} callback
372 */
373 save: function(docid, doc, options, callback) {
3742 if (arguments.length == 3 && typeof options == 'function') {
3752 callback = options;
3762 options = {};
377 }
378
3792 if (doc._rev) {
3801 this.doc(docid, options).set(doc).create(callback);
381 } else
3821 this.doc(docid, options).set(doc).save(callback);
383 },
384 /**
385 * @class
386 * @name BulkSaveOption
387 * @property {boolean=} new_edit
388 */
389 /**
390 * Create new or update docs in bulk
391 * @param {Array} docs
392 * @param {BulkSaveOption} options
393 * @param {function} callback
394 */
395 bulkSave: function(docs, options, callback) {
39615 if (arguments.length == 2 && typeof options == 'function') {
39713 callback = options;
39813 options = {};
399 }
400
40115 var json = {
402 "docs": docs
403 };
404 // put any options in the json
405 // all_or_nothing / new_edits
40615 for (var option in options) {
4070 json[option] = options[option];
408 }
409
41015 var body;
41115 try {
41215 body = JSON.stringify(json);
413 } catch (e) {
4140 return (callback && callback(e));
415 }
416
41715 this._request(this.url + "/_bulk_docs", {
418 method: 'POST',
419 body: body
420 }, function(err, results) {
42115 if (err && err.statusCode == 417) {
4220 return (callback && callback({
423 errors: results
424 }));
425 }
426
42715 if (err)
4280 return (callback && callback(err));
429
43015 for (var i = 0; i < docs.length; i++) {
43137 if (results[i].rev) {
43237 (docs[i]._id) || (docs[i]._id = results[i].id);
43337 docs[i]._rev = results[i].rev;
434 }
435 }
43615 callback && callback(err, results);
437 });
438 },
439 allDesignDocs: function(callback) {
4404 return this.searchByKeys('_design/', '_design0', function(err, ddocs) {
4414 callback && callback(err, ddocs);
442 });
443 },
444 // ==========================
445 // Revisions
446 // ==========================
447 missingRevisions: function(query, callback) {
4481 this._post(this.url + '/_missing_revs', {
449 body: JSON.stringify(query)
450 }, function(err, body) {
4511 callback && callback(err, body);
452 });
453 },
454 revisionsDiff: function(query, callback) {
4551 throw new Error('Not Implement Yet');
456 },
457 revisionsLimit: function() {
4581 var self = this;
4591 return {
460 get: function(callback) {
4611 self._get(self.url + '/_revs_limit', function(err, limit) {
4621 callback(err, limit);
463 });
464 },
465 set: function(options, callback) {
4661 var body;
4671 try {
4681 body = JSON.stringify(options);
469 } catch (e) {
4700 return (callback && callback(e));
471 }
4721 self._put(self.url + '/_revs_limit', {
473 body: body
474 }, function(err, st) {
4751 callback && callback(err, st);
476 });
477 }
478 };
479 },
480 // ==========================
481 // Security
482 // ==========================
483 security: function() {
4841 var self = this;
4851 return {
486 get: function(callback) {
4871 self._get(self.url + '/_security', function(err, sec) {
4881 callback && callback(err, sec);
489 });
490 },
491 set: function(security, callback) {
4921 var body;
4931 try {
4941 body = JSON.stringify(security);
495 } catch (e) {
4960 return (calback && callback(e));
497 }
4981 self._put(self.url + '/_security', {
499 body: body
500 }, function(err, st) {
5011 callback && callback(err, st);
502 });
503 }
504 };
505 },
506 /**
507 * @param {Object=} options options pass to follow, see follow apis
508 * @param {function=} callback if no callback is provided, a follow feed will return
509 */
510 follow: function(options, callback) {
5112 if (arguments.length === 1 && typeof options == 'function') {
5120 callback = options;
5130 options = undefined;
514 }
515
5162 options = options || {};
517
5182 options.db = this.url;
519
5202 if (callback) {
5211 return follow(options, callback);
522 } else {
5231 return new follow.Feed(options);
524 }
525 }
526});

/Users/villa/dev/personal/projects/js/node-couchdb/lib/ddoc.js

100%
50
50
0
LineHitsSource
11var _ = require('underscore'),
2 assert = require('assert'),
3 qs = require('querystring'),
4 util = require('util');
5
61var Document = require('./doc');
71var View = require('./view');
81var List = require('./list');
91var Show = require('./show');
10
111function DesignDoc(dburl, name, options) {
1219 Document.call(this, dburl, '_design/' + name, options);
1319 this.designName = name;
14
15}
16
171util.inherits(DesignDoc, Document);
18
191_.extend(DesignDoc.prototype, {
20 _encodeId: function() {
2115 return this._id;
22 },
23 info: function(callback) {
241 this._get(this.dburl + '/' + this._id + '/_info', function(err, body) {
251 callback(err, body);
26 });
27 },
28 create: function(batch, callback) {
294 var self = this;
304 if (typeof batch == 'function') {
314 callback = batch;
324 batch = undefined;
33 }
34
354 self._put(this.dburl + '/' + this._id + (batch ? ("?" + qs.stringify({
36 batch: 'ok'
37 })) : ''), {
38 body: JSON.stringify(this.doc, fnTrans)
39 }, function(err, result) {
404 if (err) return (callback && callback(err));
414 self.id(result.id);
424 self.rev(result.rev);
434 delete this.deleted;
444 callback && callback(null, result);
45 });
46 },
47 save: function(batch, callback) {
481 var self = this;
491 if (arguments.length == 1 && typeof batch == 'function') {
501 callback = batch;
511 batch = undefined;
52 }
53
541 var options = {};
551 batch && (options.batch = 'ok');
561 this._rev && (options.rev = this._rev);
57
581 self._put(this.dburl + '/' + this._id + '?' + qs.stringify(options), {
59 body: JSON.stringify(self.doc, fnTrans)
60 }, function(err, result) {
611 if (err) return (callback && callback(err));
621 self.rev(result.rev);
631 callback && callback(err, result);
64 });
65 },
66 view: function(viewname, options) {
678 return new View(this.dburl + '/' + this._id + '/_view/' + viewname, viewname, options || this.options);
68 },
69 show: function(showname, options) {
702 return new Show(this.dburl + '/' + this._id + '/_show/' + showname, showname, options || this.options);
71 },
72 list: function(listname, options) {
731 return new List(this.dburl + '/' + this._id + '/_list/' + listname, listname, options);
74 },
75 update: function(updatename, docId, options, callback) {
761 var self = this;
771 if (arguments.length == 3 && typeof options == 'function') {
781 callback = options;
791 options = undefined;
80 }
81
821 this.enableJson = false;
831 var rs = self._post(self.dburl + '/' + self._id + '/_update/' + updatename + '/' + encodeURIComponent(docId),
84 _.extend({}, options), callback);
851 this.enableJson = true;
861 return rs;
87 }
88});
89
901module.exports = DesignDoc;
91
92
93
941function fnTrans(key, value) {
95106 if (typeof value == 'function')
9628 return '(' + value.toString() + ')';
9778 return value;
98}

/Users/villa/dev/personal/projects/js/node-couchdb/lib/doc.js

100%
182
182
0
LineHitsSource
11var _ = require('underscore'),
2 assert = require('assert'),
3 util = require('util'),
4 qs = require('querystring'),
5 RequestBase = require('./base');
6
7
81function Document(dburl, doc, options) {
9 // assign alias
1049 this.delete = this.del = this.destroy;
1149 this.get = this.open;
12
1349 if (!dburl)
141 throw new Error('Database url should not be empty');
15
1648 RequestBase.call(this, options);
1748 this.dburl = dburl;
18
19
2048 if (typeof doc === 'string') {
2129 this._id = doc;
2229 doc = undefined;
23 } else {
2419 this._id = doc._id;
2519 this.set(doc);
26 }
27}
28
291util.inherits(Document, RequestBase);
30
31
321_.extend(Document.prototype, {
33 _encodeId: function() {
3431 return encodeURIComponent(this._id);
35 },
36 new: function(newDoc) {
372 if (newDoc)
381 this.doc = _.clone(newDoc);
39
402 this._id = undefined;
412 this._rev = undefined;
422 this._attachments = undefined;
432 return this;
44 },
45 id: function(id) {
4617 if (!arguments.length)
471 return this._id;
48
4916 this._id = id;
5016 this.doc && (this.doc._id = id);
5116 return this;
52 },
53 rev: function(rev) {
5440 if (!arguments.length)
554 return this._rev;
5636 this._rev = rev;
5736 this.doc && (this.doc._rev = rev);
5836 return this;
59 },
60 attach: function(attname, data, type) {
614 var atts = {};
624 if (arguments.length == 1) {
632 if (Array.isArray(attname)) {
641 attname.forEach(function(att) {
652 assert(Buffer.isBuffer(att.data) || (typeof att.data == 'string'), 'buffer must be a Buffer of String instance');
662 var data = (typeof att.data == 'string') ? new Buffer(att.data) : att.data;
672 atts[att.name] = {
68 'content_type': att.type || att.content_type,
69 'data': data.toString('base64')
70 };
71 });
72 } else {
731 for (var name in attname) {
741 var att = attname[name];
751 assert(Buffer.isBuffer(att.data) || (typeof att.data == 'string'), 'buffer must be a Buffer of String instance');
761 var data = (typeof att.data == 'string') ? new Buffer(att.data) : att.data;
771 atts[name] = {
78 'content_type': att.type || att.content_type,
79 'data': data.toString('base64')
80 };
81 }
82 }
83 } else {
842 assert(Buffer.isBuffer(data) || (typeof data == 'string'), 'buffer must be a Buffer of String instance');
852 if (typeof data == 'string')
862 data = new Buffer(data);
87
882 atts[attname] = {
89 'content_type': type,
90 'data': data.toString('base64')
91 };
92 }
93
944 this.doc && (this.doc._attachments = _.extend(this.doc._attachments || {}, atts));
954 this._attachments = _.extend(this._attachments || {}, atts);
96
974 return this;
98 },
99 update: function(newDoc) {
1002 this.doc = _.extend(this.doc, newDoc);
1012 this._id = (newDoc && newDoc._id) || this._id;
1022 this._rev = (newDoc && newDoc._rev) || this._rev;
1032 this._attachments = (newDoc && newDoc._attachments) || this._attachments;
1042 return this;
105 },
106 set: function(newDoc) {
10737 this.doc = _.clone(newDoc);
10837 this._id = (newDoc && newDoc._id) || this._id;
10937 this._rev = (newDoc && newDoc._rev) || this._rev;
11037 this._attachments = (newDoc && newDoc._attachments) || this._attachments;
11137 return this;
112 },
113 exists: function(callback) {
1145 if (this._id == null)
1151 return callback(new Error("docid must be provided"));
116
1174 this._head(this.dburl + '/' + this._encodeId(), function(err, body, res) {
1184 if (err && err.statusCode == 404) {
1192 return callback(undefined, false);
1202 } else if (!err) {
1211 return callback(undefined, true);
122 }
1231 callback(err);
124 });
125 },
126 /**
127 * @name DocHeadOptions
128 * @class
129 * @property {string} rev
130 * @property {boolean} revs
131 * @property {boolean} revs_info
132 */
133 /**
134 * @param {DocHeadOptions=} options
135 * @param {function} callback
136 */
137 head: function(options, callback) {
1383 if (arguments.length == 1) {
1391 callback = options;
1401 options = {};
141 }
142
143 /* jshint eqnull: true */
1443 if (this._id == null)
1451 return callback(new Error("docid must be provided"));
146
1472 if (this._rev)
1481 options = _.extend({
149 rev: this._rev
150 }, options);
151
1522 this._head(this.dburl + '/' + this._encodeId() + '?' + qs.stringify(options), function(err, body, res) {
1532 callback(err, res && res.headers, body);
154 });
155
1562 return this;
157 },
158 /**
159 * @name DocGetOptions
160 * @class
161 * @property {boolean} conflictss
162 * @property {string} rev
163 * @property {boolean} revs
164 * @property {boolean} revs_info
165 */
166 /**
167 * @param {DocGetOptions=} options
168 */
169 open: function(options, callback) {
17014 var self = this;
17114 if (!callback && typeof options == 'function')
17211 callback = options, options = {};
1733 else if (typeof options == 'string') {
1741 options = {
175 rev: options
176 };
177 }
17814 options = options || {};
179
18014 if (this._id === null || this._id === undefined)
1811 return (callback && callback.call(this, new Error("docid must be provided")));
182
18313 if (this._rev)
1844 options.rev = this._rev;
185
18613 var qstr = qs.stringify(options);
187
18813 var url = this.dburl + '/' + this._encodeId() + '?' + qstr;
18913 this._get(url, function(err, body) {
19013 if (!err && body) {
19112 self.set(body);
192 }
19313 callback && callback.call(self, err, body);
194 });
195 },
196 /**
197 * get a list of revisions for this document
198 */
199 revisions: function(callback) {
2002 this.open({
201 revs: true
202 }, function(err, doc) {
2033 if (err) return (callback && callback(err));
2041 callback && callback(err, doc._revisions, doc);
205 });
206 },
207 create: function(batch, callback) {
20812 var self = this;
20912 if (typeof batch == 'function') {
21011 callback = batch;
21111 batch = undefined;
212 }
213
21412 self._post(this.dburl + (batch ? ("?" + qs.stringify({
215 batch: 'ok'
216 })) : ''), {
217 body: JSON.stringify(this.doc)
218 }, function(err, result) {
21912 if (err) return (callback && callback(err));
22012 self.id(result.id);
22112 self.rev(result.rev);
22212 delete this.deleted;
22312 callback && callback(null, result);
224 });
225 },
226 save: function(batch, callback) {
2274 var self = this;
2284 if (arguments.length == 1 && typeof batch == 'function') {
2294 callback = batch;
2304 batch = undefined;
231 }
232
2334 var options = {};
2344 batch && (options.batch = 'ok');
2354 this._rev && (options.rev = this._rev);
236
2374 self._put(this.dburl + '/' + this._encodeId() + '?' + qs.stringify(options), {
238 body: JSON.stringify(self.doc)
239 }, function(err, result) {
2404 if (err) return (callback && callback(err));
2414 self.rev(result.rev);
2424 callback && callback(err, result);
243 });
244 },
245 destroy: function(rev, callback) {
2465 if (arguments.length == 1 && typeof rev == 'function') {
2475 callback = rev;
2485 rev = undefined;
249 }
250
2515 rev = rev || this._rev;
252
253 /* jshint eqnull: true */
2545 if (this._id == null)
2551 return (callback && callback(new Error("docid must be provided")));
256
2574 if (rev == null)
2581 return (callback && callback(new Error("revision must be provided")));
259
2603 var self = this;
2613 self._delete(self.dburl + '/' + this._encodeId() + '?' + qs.stringify({
262 rev: rev
263 }), function(err, result) {
2643 if (self.doc)
2653 self.doc._deleted = true;
2663 self.deleted = true;
2673 callback && callback(err, result);
268 });
269 },
270 /**
271 * @name DocCopyOptions
272 * @class
273 * @property {string} from_rev
274 * @property {string} to_rev
275 */
276 /**
277 * @param {string} id
278 * @param {DocCopyOptions=} options
279 * @param {function} callback
280 */
281 copy: function(id, options, callback) {
2822 var self = this;
2832 if (arguments.length == 2 && typeof options == 'function') {
2842 callback = options;
2852 options = undefined;
286 }
287
2882 options = options || {};
289
2902 this._copy(this.dburl + '/' + this._encodeId() + ((options.from_rev || this._rev) ? ('?' + qs.stringify({
291 rev: options.from_rev || this._rev
292 })) : ''), {
293 headers: {
294 Destination: id + (options.to_rev ? ('?' + qs.stringify({
295 rev: options.to_rev
296 })) : '')
297 }
298 }, function(err, rs) {
299 // TODO: discuss does it right to call the callback in context
3002 callback && callback.call(self, err, rs);
301 });
302 },
303 // =========================
304 // Attachment
305 // =========================
306 addAttachment: function(attname, data, type, callback) {
30712 var self = this;
308
309 /* jshint eqnull: true */
31012 if (this._id == null)
3111 return (callback && callback(new Error("docid must be provided")));
312
31311 if (this._rev == null)
3141 return (callback && callback(new Error("revision must be provided")));
315
316
31710 if (arguments.length == 2 && typeof data == 'function') {
3183 callback = data;
319 // above 1.3.x ?
3203 var atts = {},
321 mps = [],
322 headers = {
323 'Content-Type': 'multipart/related'
324 };
325
3263 if (Array.isArray(attname)) {
3272 attname.forEach(function(att) {
3284 atts[att.name] = {
329 follows: true,
330 length: att.data.length,
331 content_type: att.type || att.content_type
332 };
3334 mps.push({
334 body: att.data
335 });
336 });
337 } else {
3381 for (var name in attname) {
3391 var att = attname[name];
3401 atts[name] = {
341 follows: true,
342 length: att.data.length,
343 content_type: att.type || att.content_type
344 };
3451 mps.push({
346 body: att.data
347 });
348 }
349 }
350
3513 mps.unshift({
352 'Content-Type': 'application/json',
353 body: JSON.stringify(_.extend({}, this.doc, {
354 _attachments: atts
355 }))
356 });
357
3583 return this._put(this.dburl + '/' + this._encodeId(), {
359 headers: headers,
360 multipart: mps
361 }, function(err, rs, res) {
3623 if (err) return (callback && callback(err));
3633 self.rev(rs.rev);
3643 callback && callback(err, rs);
365 });
366 } else {
367
3687 var headers = {
369 'Content-Type': type
370 };
371
3727 data && (headers['Content-Length'] = data.length);
373
3747 assert(!data || Buffer.isBuffer(data) || (typeof data == 'string'), 'buffer must be a Buffer of String instance');
3757 return this._put([this.dburl, '/', this._encodeId(), '/', encodeURIComponent(attname),
376 '?', this._rev ? qs.stringify({
377 rev: this._rev
378 }) : ''
379 ].join(''), {
380 headers: headers,
381 body: data
382 },
383 function(err, body, res) {
3847 body && body.rev && self.rev(body.rev);
3857 callback && callback(err, body, res);
386 });
387 }
388 },
389 getAttachment: function(attname, callback) {
3905 return this._get(this.dburl + '/' + this._encodeId() + '/' + encodeURIComponent(attname), {
391 headers: {
392 'Content-Type': 'multipart/related'
393 }
394 }, function(err, buffer) {
3955 callback && callback(err, buffer);
396 });
397 },
398 delAttachment: function(attname, callback) {
3993 var self = this,
400 query = {};
4013 this._rev && (query.rev = this._rev);
4023 return this._delete(this.dburl + '/' + this._encodeId() + '/' + encodeURIComponent(attname) + '?' +
403 qs.stringify(query), function(err, body) {
4043 if (err) return (callback && callback(err));
405
4063 self.rev(body.rev);
4073 callback && callback(err, body);
408 });
409 },
410 attachment: function(name) {
4114 var self = this;
4124 return {
413 attach: function(data, type, callback) {
4141 self.addAttachment(name, data, type, callback);
415 },
416 get: function(callback) {
4173 self.getAttachment(name, callback);
418 },
419 update: function(data, type, callback) {
4201 self.addAttachment(name, data, type, callback);
421 },
422 del: function(callback) {
4231 self.delAttachment(name, callback);
424 }
425 };
426 }
427});
428
429
430
4311module.exports = Document;

/Users/villa/dev/personal/projects/js/node-couchdb/lib/exec.js

100%
31
31
0
LineHitsSource
11var _ = require('underscore');
2
31function capital(str) {
4139 if (str)
5138 return str.charAt(0).toUpperCase() + str.slice(1);
61 return '';
7}
8
91function Executor() {
1027 var self = this;
1127 this.options = {};
12
1327 Array.prototype.forEach.call(arguments, function(prop) {
14419 addProperty(prop);
15 });
16
1727 function addProperty(prop) {
18421 if (prop instanceof Array) {
191 prop.forEach(addProperty);
20420 } else if (typeof prop == 'string') {
21395 var method = prop.split('_').map(function(val, idx) {
22534 if (idx === 0)
23395 return val;
24139 return capital(val);
25 }).join('');
26395 if (!self[method]) {
27395 self[method] = function(val) {
28 /* jshint eqnull: true */
2928 if (val != null)
3026 self.options[prop] = val;
3128 return this;
32 };
33 }
34 }
35 }
36}
37
38
391Executor.prototype.set = function(options) {
4014 if (options)
415 this.options = _.extend(this.options, options);
42
4314 return this;
44};
45
46
471Executor.prototype.exec = function() {
487 return this.execute.apply(this, arguments);
49};
50
511Executor.prototype.execute = function() {};
52
531module.exports = Executor;

/Users/villa/dev/personal/projects/js/node-couchdb/lib/index.js

100%
10
10
0
LineHitsSource
11var CouchDB = require('./couch');
2
31module.exports = function(url, options) {
41 return new CouchDB(url, options);
5};
6
71module.exports.CouchDB = CouchDB;
81module.exports.Database = require('./db');
91module.exports.Document = require('./doc');
101module.exports.DesignDoc = require('./ddoc');
111module.exports.View = require('./view');
121module.exports.List = require('./list');
131module.exports.Show = require('./show');

/Users/villa/dev/personal/projects/js/node-couchdb/lib/list.js

100%
17
17
0
LineHitsSource
11var _ = require('underscore'),
2 util = require('util'),
3 RequestBase = require('./base');
4
51module.exports = List;
6
71function List(url, listName, options) {
81 RequestBase.call(this, options);
91 this.url = url.replace(/\/$/, '');
101 this.listName = listName;
11}
12
131util.inherits(List, RequestBase);
14
151List.prototype.view = function(viewname, options, callback) {
161 if (arguments.length == 2 && typeof options == 'function') {
171 callback = options;
181 options = undefined;
19 }
201 options = options || {};
211 options.method = options.method || 'GET';
22
231 this.enableJson = false;
241 var rs = this._request(this.url + '/' + viewname, options, callback);
251 this.enableJson = true;
261 return rs;
27};

/Users/villa/dev/personal/projects/js/node-couchdb/lib/local.js

100%
6
6
0
LineHitsSource
11var _ = require('underscore'),
2 util = require('util'),
3 RequestBase = require('./base');
4
5
61function Local(url, options) {
71 RequestBase.call(this, options);
8}
9
101util.inherits(Local, RequestBase);
11
12// TODO:
131_.extend(Local.prototype, {
14 create: function() {
15
16 },
17 get: function() {
18
19 },
20 update: function() {
21
22 },
23 delete: function() {
24
25 },
26 copy: function() {
27
28 }
29});
30
311module.exports = Local;

/Users/villa/dev/personal/projects/js/node-couchdb/lib/show.js

100%
26
26
0
LineHitsSource
11var _ = require('underscore'),
2 util = require('util'),
3 RequestBase = require('./base');
4
51module.exports = Show;
6
71function Show(url, showName, options) {
82 RequestBase.call(this, options);
92 this.url = url.replace(/\/$/, '');
102 this.showName = showName;
11}
12
131util.inherits(Show, RequestBase);
14
151Show.prototype.doc = function(docid, options, callback) {
161 if (arguments.length == 2 && typeof options == 'function') {
171 callback = options;
181 options = undefined;
19 }
20
211 options = options || {};
221 options.method = options.method || 'GET';
23
241 this.enableJson = false;
251 var rs = this._request(this.url + '/' + encodeURIComponent(docid), options, callback);
261 this.enableJson = true;
271 return rs;
28};
29
30
311Show.prototype.get = function(options, callback) {
321 if (arguments.length == 1 && typeof options == 'function') {
331 callback = options;
341 options = undefined;
35 }
36
371 options = options || {};
38
391 this.enableJson = false;
401 var rs = this._get(this.url, options, callback);
411 this.enableJson = true;
421 return rs;
43
44};

/Users/villa/dev/personal/projects/js/node-couchdb/lib/view.js

100%
39
39
0
LineHitsSource
11var _ = require('underscore'),
2 util = require('util'),
3 qs = require('querystring'),
4 Executor = require('./exec'),
5 RequestBase = require('./base');
6
7
81function View(url, viewName, options) {
98 RequestBase.call(this, options);
108 this.url = url.replace(/\/$/, '');
118 this.viewName = viewName;
12}
13
141util.inherits(View, RequestBase);
15
161_.extend(View.prototype, {
17 fetch: function(key, callback) {
181 this.query().includeDocs(true).key(key).execute(callback);
19 },
20 mfetch: function(keys, callback) {
211 this.query().includeDocs(true).keys(keys).execute(callback);
22 },
23 /**
24 *
25 */
26 query: function(options) {
278 var self = this,
28 // use additions to extend properties for future or higher version couchdb
29 executor = new Executor(View.prototype.query.additions, 'conflicts', 'skip', 'limit', 'descending', 'endkey', 'startkey', 'endkey_docid', 'startkey_docid',
30 'group', 'group_level', 'include_docs', 'inclusive_end', 'key', 'keys', 'reduce', 'stale', 'update_seq');
31
328 executor.betweenIds = function(startid, endid) {
331 this.options.startkey_docid = startid;
341 this.options.endkey_docid = endid;
351 return this;
36 };
37
388 executor.betweenKeys = function(startkey, endkey) {
391 this.options.startkey = startkey;
401 this.options.endkey = endkey;
411 return this;
42 };
43
448 executor.execute = function(callback) {
458 var opts = _.clone(this.options);
46
478 try {
488 ['startkey', 'endkey', 'key'].forEach(function(p) {
4924 opts[p] && (opts[p] = JSON.stringify(opts[p]));
50 });
51 } catch (e) {
521 return (callback && callback(e));
53 }
54
55
567 if (opts.keys && opts.keys.length) {
571 var keys = opts.keys;
581 delete opts.keys;
591 self._post(self.url + '?' + qs.stringify(opts), {
60 body: JSON.stringify({
61 keys: keys
62 })
63 }, function(err, body) {
641 if (err) return (callback && callback(err));
651 callback && callback(err, body.rows, body.total_rows, body.offset, body);
66 });
67
68 } else {
696 self._get(self.url + '?' + qs.stringify(opts), function(err, body) {
706 if (err) return (callback && callback(err));
716 callback && callback(err, body.rows, body.total_rows, body.offset, body);
72 });
73 }
74 };
75
768 if (options) {
772 if (typeof options == 'function') {
781 executor.exec(options);
79 } else
801 executor.set(options);
81 }
82
838 return executor;
84 }
85});
86
87
881module.exports = View;