From aedc9411747ede5ad9a786378eeac645b8c94cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Kussmann?= Date: Sat, 28 Mar 2015 14:36:43 +0100 Subject: [PATCH] fixed jshint and tests with newer versions of jshint, mocha and chai --- .jshintrc | 88 +- config.js | 3 - cushion.browser.js | 4105 ---------------------------------------- cushion.browser.min.js | 2 - package.json | 11 +- test/testrunner.js | 105 +- 6 files changed, 87 insertions(+), 4227 deletions(-) delete mode 100644 cushion.browser.js delete mode 100644 cushion.browser.min.js diff --git a/.jshintrc b/.jshintrc index 2fcd3db..b4c887b 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,48 +1,42 @@ { - "asi": true, // always use semicolons - "bitwise": true, // not using bitwise operators - "boss": true, // no use of assignments, where comparisons are expected - "camelcase": true, // always camelcasing - "curly": true, // never use blocks without the curly braces - "debug": false, // not using debugger for production code - "eqeqeq": true, // always use === and !== and not == and != - "eqnull": false, // always check to null with == and not === - "esnext": false, // not use ES.next features like "const" - "evil": false, // never user eval (because it's evil) - "forin": true, // for in loops have to filter for Object.hasOwnProperty - "funcscope": false, // never declare variables in blocks othen than functions - "globalstrict": true, // use global strict mode - "immed": false, // parens around functions are ok - "indent": 2, // 2 spaces indentation - "iterator": true, // because we are in nodejs, we can use __iterator__ - "lastsemic": false, // don't miss semicolons - "latedef": true, // explicitely define variables - "laxbreak": false, // warn us about unsafe line breaks - "laxcomma": false, // do not use comma-first style - "loopfunc": false, // do not define functions inside of a loop block - "maxdepth": 2, // maximum nesting blocks - "maxlen": 80, // no line longer than this - "multistr": false, // correct using of multiline strings - "newcap": true, // constructor name always begins with an uppercase letter - "noarg": true, // not using arguments.callee and arguments.caller - "node": true, // we are using nodejs - "noempty": true, // no empty blocks - "nomen": false, // using dangling _ for "private" things is allowed - "nonew": true, // no new MyConstructor without assigning to a variable - "onecase": false, // do not use switch, if an if-block will be better - "onevar": true, // only use one var statement per function - "plusplus": false, // we allow ++ and -- - "proto": true, // we are in nodejs, so we can use __proto__ - "quotmark": "single", // only using single quotes for strings - "regexdash": false, // not use unescaped - at the end of regular expressions - "shadow": false, // do not redeclare a variable - "smarttabs": false, // do not use tabs and spaces for indentation - "strict": true, // ecmascript strict mode for function scopes - "sub": false, // dot notation over braces notation - "supernew": false, // do not use new Object or new function or something like - "trailing": true, // no trailing whitespaces - "undef": true, // always declare variables - "unused": true, // mark variables that will never used - "validthis": false, // correct using of this, especially in strict mode - "white": false // strict whitespace would be cool, but it has errors -} \ No newline at end of file + "asi": false, + "bitwise": true, + "boss": false, + "curly": true, + "debug": false, + "elision": false, + "eqeqeq": true, + "eqnull": false, + "es3": false, + "esnext": true, + "evil": false, + "expr": false, + "forin": true, + "freeze": true, + "funcscope": false, + "futurehostile": true, + "globalstrict": true, + "iterator": false, + "lastsemic": true, + "latedef": true, + "loopfunc": false, + "maxdepth": 3, + "maxparams": 8, + "maxstatements": 20, + "noarg": true, + "nocomma": true, + "node": true, + "nonbsp": true, + "nonew": true, + "notypeof": true, + "noyield": false, + "plusplus": false, + "proto": false, + "shadow": false, + "singleGroups": false, + "supernew": false, + "undef": true, + "unused": true, + "validthis": false, + "withstmt": false +} diff --git a/config.js b/config.js index dd45887..274bf28 100644 --- a/config.js +++ b/config.js @@ -1,6 +1,3 @@ -// jshint settings -/*global exports: false */ - exports.host = '127.0.0.1'; exports.port = 5984; exports.username = ''; diff --git a/cushion.browser.js b/cushion.browser.js deleted file mode 100644 index 58a1aea..0000000 --- a/cushion.browser.js +++ /dev/null @@ -1,4105 +0,0 @@ -(function(){var require = function (file, cwd) { - var resolved = require.resolve(file, cwd || '/'); - var mod = require.modules[resolved]; - if (!mod) throw new Error( - 'Failed to resolve module ' + file + ', tried ' + resolved - ); - var cached = require.cache[resolved]; - var res = cached? cached.exports : mod(); - return res; -}; - -require.paths = []; -require.modules = {}; -require.cache = {}; -require.extensions = [".js",".coffee",".json"]; - -require._core = { - 'assert': true, - 'events': true, - 'fs': true, - 'path': true, - 'vm': true -}; - -require.resolve = (function () { - return function (x, cwd) { - if (!cwd) cwd = '/'; - - if (require._core[x]) return x; - var path = require.modules.path(); - cwd = path.resolve('/', cwd); - var y = cwd || '/'; - - if (x.match(/^(?:\.\.?\/|\/)/)) { - var m = loadAsFileSync(path.resolve(y, x)) - || loadAsDirectorySync(path.resolve(y, x)); - if (m) return m; - } - - var n = loadNodeModulesSync(x, y); - if (n) return n; - - throw new Error("Cannot find module '" + x + "'"); - - function loadAsFileSync (x) { - x = path.normalize(x); - if (require.modules[x]) { - return x; - } - - for (var i = 0; i < require.extensions.length; i++) { - var ext = require.extensions[i]; - if (require.modules[x + ext]) return x + ext; - } - } - - function loadAsDirectorySync (x) { - x = x.replace(/\/+$/, ''); - var pkgfile = path.normalize(x + '/package.json'); - if (require.modules[pkgfile]) { - var pkg = require.modules[pkgfile](); - var b = pkg.browserify; - if (typeof b === 'object' && b.main) { - var m = loadAsFileSync(path.resolve(x, b.main)); - if (m) return m; - } - else if (typeof b === 'string') { - var m = loadAsFileSync(path.resolve(x, b)); - if (m) return m; - } - else if (pkg.main) { - var m = loadAsFileSync(path.resolve(x, pkg.main)); - if (m) return m; - } - } - - return loadAsFileSync(x + '/index'); - } - - function loadNodeModulesSync (x, start) { - var dirs = nodeModulesPathsSync(start); - for (var i = 0; i < dirs.length; i++) { - var dir = dirs[i]; - var m = loadAsFileSync(dir + '/' + x); - if (m) return m; - var n = loadAsDirectorySync(dir + '/' + x); - if (n) return n; - } - - var m = loadAsFileSync(x); - if (m) return m; - } - - function nodeModulesPathsSync (start) { - var parts; - if (start === '/') parts = [ '' ]; - else parts = path.normalize(start).split('/'); - - var dirs = []; - for (var i = parts.length - 1; i >= 0; i--) { - if (parts[i] === 'node_modules') continue; - var dir = parts.slice(0, i + 1).join('/') + '/node_modules'; - dirs.push(dir); - } - - return dirs; - } - }; -})(); - -require.alias = function (from, to) { - var path = require.modules.path(); - var res = null; - try { - res = require.resolve(from + '/package.json', '/'); - } - catch (err) { - res = require.resolve(from, '/'); - } - var basedir = path.dirname(res); - - var keys = (Object.keys || function (obj) { - var res = []; - for (var key in obj) res.push(key); - return res; - })(require.modules); - - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - if (key.slice(0, basedir.length + 1) === basedir + '/') { - var f = key.slice(basedir.length); - require.modules[to + f] = require.modules[basedir + f]; - } - else if (key === basedir) { - require.modules[to] = require.modules[basedir]; - } - } -}; - -(function () { - var process = {}; - - require.define = function (filename, fn) { - if (require.modules.__browserify_process) { - process = require.modules.__browserify_process(); - } - - var dirname = require._core[filename] - ? '' - : require.modules.path().dirname(filename) - ; - - var require_ = function (file) { - var requiredModule = require(file, dirname); - var cached = require.cache[require.resolve(file, dirname)]; - - if (cached && cached.parent === null) { - cached.parent = module_; - } - - return requiredModule; - }; - require_.resolve = function (name) { - return require.resolve(name, dirname); - }; - require_.modules = require.modules; - require_.define = require.define; - require_.cache = require.cache; - var module_ = { - id : filename, - filename: filename, - exports : {}, - loaded : false, - parent: null - }; - - require.modules[filename] = function () { - require.cache[filename] = module_; - fn.call( - module_.exports, - require_, - module_, - module_.exports, - dirname, - filename, - process - ); - module_.loaded = true; - return module_.exports; - }; - }; -})(); - - -require.define("path",function(require,module,exports,__dirname,__filename,process){function filter (xs, fn) { - var res = []; - for (var i = 0; i < xs.length; i++) { - if (fn(xs[i], i, xs)) res.push(xs[i]); - } - return res; -} - -// resolves . and .. elements in a path array with directory names there -// must be no slashes, empty elements, or device names (c:\) in the array -// (so also no leading and trailing slashes - it does not distinguish -// relative and absolute paths) -function normalizeArray(parts, allowAboveRoot) { - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = parts.length; i >= 0; i--) { - var last = parts[i]; - if (last == '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); - } - } - - return parts; -} - -// Regex to split a filename into [*, dir, basename, ext] -// posix version -var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/; - -// path.resolve([from ...], to) -// posix version -exports.resolve = function() { -var resolvedPath = '', - resolvedAbsolute = false; - -for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) - ? arguments[i] - : process.cwd(); - - // Skip empty and invalid entries - if (typeof path !== 'string' || !path) { - continue; - } - - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; -} - -// At this point the path should be resolved to a full absolute path, but -// handle relative paths to be safe (might happen when process.cwd() fails) - -// Normalize the path -resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); - - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; -}; - -// path.normalize(path) -// posix version -exports.normalize = function(path) { -var isAbsolute = path.charAt(0) === '/', - trailingSlash = path.slice(-1) === '/'; - -// Normalize the path -path = normalizeArray(filter(path.split('/'), function(p) { - return !!p; - }), !isAbsolute).join('/'); - - if (!path && !isAbsolute) { - path = '.'; - } - if (path && trailingSlash) { - path += '/'; - } - - return (isAbsolute ? '/' : '') + path; -}; - - -// posix version -exports.join = function() { - var paths = Array.prototype.slice.call(arguments, 0); - return exports.normalize(filter(paths, function(p, index) { - return p && typeof p === 'string'; - }).join('/')); -}; - - -exports.dirname = function(path) { - var dir = splitPathRe.exec(path)[1] || ''; - var isWindows = false; - if (!dir) { - // No dirname - return '.'; - } else if (dir.length === 1 || - (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) { - // It is just a slash or a drive letter with a slash - return dir; - } else { - // It is a full dirname, strip trailing slash - return dir.substring(0, dir.length - 1); - } -}; - - -exports.basename = function(path, ext) { - var f = splitPathRe.exec(path)[2] || ''; - // TODO: make this comparison case-insensitive on windows? - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); - } - return f; -}; - - -exports.extname = function(path) { - return splitPathRe.exec(path)[3] || ''; -}; - -}); - -require.define("__browserify_process",function(require,module,exports,__dirname,__filename,process){var process = module.exports = {}; - -process.nextTick = (function () { - var canSetImmediate = typeof window !== 'undefined' - && window.setImmediate; - var canPost = typeof window !== 'undefined' - && window.postMessage && window.addEventListener - ; - - if (canSetImmediate) { - return window.setImmediate; - } - - if (canPost) { - var queue = []; - window.addEventListener('message', function (ev) { - if (ev.source === window && ev.data === 'browserify-tick') { - ev.stopPropagation(); - if (queue.length > 0) { - var fn = queue.shift(); - fn(); - } - } - }, true); - - return function nextTick(fn) { - queue.push(fn); - window.postMessage('browserify-tick', '*'); - }; - } - - return function nextTick(fn) { - setTimeout(fn, 0); - }; -})(); - -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; - -process.binding = function (name) { - if (name === 'evals') return (require)('vm') - else throw new Error('No such module. (Possibly not yet loaded)') -}; - -(function () { - var cwd = '/'; - var path; - process.cwd = function () { return cwd }; - process.chdir = function (dir) { - if (!path) path = require('path'); - cwd = path.resolve(dir, cwd); - }; -})(); - -}); - -require.define("/package.json",function(require,module,exports,__dirname,__filename,process){module.exports = {"main":"./cushion"} -}); - -require.define("/cushion.js",function(require,module,exports,__dirname,__filename,process){// jshint settings -/*global require: false, exports: false */ - -var http = require('http'), - defaultOptions = require('./config.js'), - Database = require('./database.js').Database, - UserApi = require('./user.js').User; - -/** - * create connection to a couchdb - * - * @param {string} [host=this._options.host] host address - * @param {number} [port=this._options.port] port - * @param {string} [username=this._options.username] username for authorization - * @param {string} [password=this._options.password] password for authorization - * @param {object} additional additional options: - * {boolean} [secure=false] set this to true, if you want https-connections - * {string} [path=''] set an additional path, if you want to connect through - * this (e.g. a proxy, because of connecting from browser) - */ -var cushion = function(host, port, username, password, additional) { - additional = additional || {}; - - this._methodMatch = /^GET|PUT|POST|DELETE|HEAD|COPY$/i; - this._options = { - 'host': host || defaultOptions.host, - 'port': port || defaultOptions.port, - 'username': username || defaultOptions.username, - 'password': password || defaultOptions.password, - 'secure': additional.secure || defaultOptions.secure, - 'path': (additional.path) ? additional.path + '/' : defaultOptions.path - }; - - if (this._options.secure === true) { - http = require('https'); - } -}; - - -/** - * returns a list of active tasks - * - * @param {function(error, activeTasks)} callback function that will called, - * after getting the list of active tasks or if there was an error - */ -cushion.prototype.activeTasks = function(callback) { - this.request({ - 'method': 'GET', - 'path': '_active_tasks', - 'callback': callback - }); -}; - - -/** - * set or get configuration params - * if you set: - * one param: you will get the complete configuration - * two params: you will get all options of the specific section - * three params: you will get the content of the specific option - * four params: you set a specific option to the new value, or you delete the - * given option, if you set value to null - * - * @param {string|function(error, configuration)} sectionOrCallback a section of - * different config params or function that will be called, after getting - * the whole configuration or if there was an error - * @param {?string|function(error, options)} optionOrCallback an specific option - * or a function, that will be called, after getting the options of the - * section of if there was an error - * @param {?string|function(error, value)} valueOrCallback the new value for the - * option or function that will be called, after getting the content of the - * option; if you set the value to null, option will be deleted - * @param {?function(error, saved)} callback function that will be called after - * saving the new value, or if there was an error - */ -cushion.prototype.config = function( - sectionOrCallback, - optionOrCallback, - valueOrCallback, - callback -) { - var section = (typeof(sectionOrCallback) === 'string') ? - sectionOrCallback : - null, - option = (typeof(optionOrCallback) === 'string') ? - optionOrCallback : - null, - value = ( - typeof(valueOrCallback) === 'string' || - typeof(valueOrCallback) === 'number' || - valueOrCallback === null - ) ? valueOrCallback : undefined, - options; - callback = callback || - valueOrCallback || - optionOrCallback || - sectionOrCallback; - - options = { - 'method': (value !== undefined) ? - ((value === null) ? 'DELETE' : 'PUT') : - 'GET', - 'path': '_config' + - ((section) ? '/' + section : '') + - ((option) ? '/' + option : ''), - 'callback': function(error, response) { - if (error) { - response = null; - } else { - response = (value !== undefined) ? true : response; - } - - callback(error, response); - } - }; - - // do we set a new value? - if (typeof(value) === 'string' || typeof(value) === 'number') { - options.body = '"' + value + '"'; - } - - this.request(options); -}; - - -/** - * creates an admin - * - * @param {string} name name of the admin account - * @param {string} password password of the admin account - * @param {function(error, created)} callback function that will be called after - * creating the admin account, or if there was an error - */ -cushion.prototype.createAdmin = function(name, password, callback) { - // first we have to create a new option at the config - this.config('admins', name, password, (function(error, created) { - // after that we have to create a user document - var database, - document; - - if (created === true) { - database = this.database('_users'); - document = database.document('org.couchdb.user:' + name); - document.body('name', name); - document.body('type', 'user'); - document.body('roles', []); - document.save(function(error, document) { - if (error) { - callback(error, null); - } else { - callback(error, true); - } - }); - } else { - callback(error, null); - } - }).bind(this)); -}; - - -/** - * gives a connection to a specific database - * - * @param {string} name name of the database - * @return {Object} the database object - */ -cushion.prototype.database = function(name) { - return new Database(name, this); -}; - - -/** - * deletes an admin - * - * @param {string} name username of the admin - * @param {function(error, deleted)} callback function that will be called, - * after deleting the admin account, or if there was an error - */ -cushion.prototype.deleteAdmin = function(name, callback) { - // first we have to delete the admin option - this.config('admins', name, null, (function(error, deleted) { - // after that we have to delete the user document - var database, - document; - - if (deleted === true) { - database = this.database('_users'); - document = database.document('org.couchdb.user:' + name); - document.load(function(error, document) { - if (document) { - document.destroy(function(error, document) { - if (document) { - callback(null, true); - } else { - callback(error, null); - } - }); - } else { - callback(error, null); - } - }); - } else { - callback(error, null); - } - }).bind(this)); -}; - - -/** - * retrieving a list of databases - * - * - * @param {boolean|function(error, databases)} noCouchRelatedOrCallback filters - * all couch related databases, so the list has only databases which a user - * has set up or function that will be called after retrieving a list of - * databases, or if there was an error - * @param {?function()} callback function that will be called after retrieving a - * list of databases, or if there was an error - */ - -cushion.prototype.listDatabases = function(noCouchRelatedOrCallback, callback) { - var noCouchRelated = (callback) ? noCouchRelatedOrCallback : null; - callback = callback || noCouchRelatedOrCallback; - - this.request({ - 'method': 'GET', - 'path': '_all_dbs', - 'callback': (function (error, response) { - if (error === null && response !== null) { - // filter couch related databases, if user want's so - if (noCouchRelated === true) { - response = response.filter(function(dbName, index, list) { - return (dbName[0] !== '_'); - }); - } - - // create database objects - response = response.map(function(dbName) { - return this.database(dbName); - }, this); - } - - callback(error, response); - }).bind(this) - }); -}; - - -/** - * returns the tail of the server's log file - * - * @param {number|function(error, log)} bytesOrCallback number of bytes how many - * do you want from the tail or function that will be called, after getting - * the log or if there was an error - * @param {?function(error, log)} callback function that will be called, after - * getting the log or if there was an error - */ -cushion.prototype.log = function(bytesOrCallback, callback) { - var bytes = (arguments.length > 1) ? bytesOrCallback : null; - callback = callback || bytesOrCallback; - - this.request({ - 'method': 'GET', - 'path': '_log' + ((bytes) ? '?bytes=' + bytes : ''), - 'callback': callback - }); -}; - - -/** - * wrapper function for any request to the couchdb - * - * @param {Function} callback function that will be called after all data events - * @param {http.ClientResponse} response the http response object - */ -cushion.prototype._request = function(callback, response) { - var content = ''; - - response.on('data', function(chunk) { - content += chunk; - }); - - response.on('end', (function() { - try { - if ( - response.headers['content-type'] === 'application/json' && - content.length > 0 - ) { - content = JSON.parse(content); - } - - if (response.statusCode === 404 && content.length === 0) { - content = { - 'error': 'not_found', - 'reason': 'missing' - }; - } - - callback( - (content.error) ? content : null, - (!content.error) ? content : null, - response.headers || null - ); - } catch(error) { - callback(error, null, null); - } - }).bind(this)); -}; - - -/** - * sends a request to the couch - * - * @param {object} properties options for the request - * method: {string} http method, can be GET, PUT, POST, DELETE, HEAD, COPY - * path: {string} uri path after domain - * headers: {Object} key/value-pairs of additional http headers - * body: {Object|Array} additional body - * callback: {function(error, response)} function that will be called, - * after getting the response or if there was an error - */ -cushion.prototype.request = function(properties) { - var options = { - 'host': this._options.host, - 'port': this._options.port, - 'method': ( - typeof(properties.method) === 'string' && - properties.method.match(this._methodMatch) !== null - ) ? - properties.method : - 'GET', - 'path': '/' + this._options.path + (properties.path || ''), - 'auth': this._options.username + ':' + this._options.password, - 'headers': properties.headers || {} - }, - request; - - // make sure, that we get application/json response from couchdb - options.headers.Accept = options.headers.Accept || '*/*,application/json'; - options.headers['Content-Type'] = options.headers['Content-Type'] || - 'application/json'; - - // set up request object - request = http.request( - options, - this._request.bind(this, properties.callback) - ); - - // define callback, if there is an error - request.on('error', (function(error) { - properties.callback(error, null, null); - }).bind(this)); - - // adding optional body to the request - if (properties.body) { - if (typeof(properties.body) === 'object') { - request.write(JSON.stringify(properties.body)); - } else { - request.write(properties.body); - } - } - - // starting request - request.end(); -}; - - -/** - * restarts the couchdb - * - * @param {function(error, restart)} callback function that will be called, - * after initializing the restart or if there was an error - */ -cushion.prototype.restart = function(callback) { - this.request({ - 'method': 'POST', - 'path': '_restart', - 'callback': function(error, restart) { - if (error && error.code === 'ECONNRESET') { - error = null; - restart = true; - } - - callback(error, restart); - } - }); -}; - - -/** - * returns server statistics - * - * @param {function(error, stats)} callback function that will be called, after - * getting the statistics of if there was an error - */ -cushion.prototype.stats = function(callback) { - this.request({ - 'method': 'GET', - 'path': '_stats', - 'callback': callback - }); -}; - - -/** - * get the user object - * - * @return {cushion.User} the user object - */ -cushion.prototype.user = function() { - return new UserApi(this); -}; - - -/** - * returns a list of generated uuids - * - * @param {number|function(error, uuidList)} countOrCallback number of uuids to - * generate or function that will be called, after getting the list of uuids - * or if there was an error - * @param {?function(error, uuidList)} callback function that will be called, - * after getting the list of uuids or if there was an error - */ -cushion.prototype.uuids = function(countOrCallback, callback) { - var count = (arguments.length > 1) ? countOrCallback : null; - callback = callback || countOrCallback; - - this.request({ - 'method': 'GET', - 'path': '_uuids' + ((count) ? '?count=' + count : ''), - 'callback': function(error, uuidList) { - if (uuidList) { - uuidList = uuidList.uuids; - } - - callback(error, uuidList); - } - }); -}; - - -/** - * gets the version of the couchdb - * - * @param {Function(version)} callback function that will be called after - */ -cushion.prototype.version = function(callback) { - this.request({ - 'method': 'GET', - 'path': '', - 'callback': function(error, response) { - if (response !== null) { - response = response.version; - } - - callback(error, response); - } - }); -}; - - -exports.Connection = cushion; - -}); - -require.define("http",function(require,module,exports,__dirname,__filename,process){module.exports = require("http-browserify") -}); - -require.define("/node_modules/http-browserify/package.json",function(require,module,exports,__dirname,__filename,process){module.exports = {"main":"index.js","browserify":"index.js"} -}); - -require.define("/node_modules/http-browserify/index.js",function(require,module,exports,__dirname,__filename,process){var http = module.exports; -var EventEmitter = require('events').EventEmitter; -var Request = require('./lib/request'); - -http.request = function (params, cb) { - if (!params) params = {}; - if (!params.host) params.host = window.location.host.split(':')[0]; - if (!params.port) params.port = window.location.port; - - var req = new Request(new xhrHttp, params); - if (cb) req.on('response', cb); - return req; -}; - -http.get = function (params, cb) { - params.method = 'GET'; - var req = http.request(params, cb); - req.end(); - return req; -}; - -http.Agent = function () {}; -http.Agent.defaultMaxSockets = 4; - -var xhrHttp = (function () { - if (typeof window === 'undefined') { - throw new Error('no window object present'); - } - else if (window.XMLHttpRequest) { - return window.XMLHttpRequest; - } - else if (window.ActiveXObject) { - var axs = [ - 'Msxml2.XMLHTTP.6.0', - 'Msxml2.XMLHTTP.3.0', - 'Microsoft.XMLHTTP' - ]; - for (var i = 0; i < axs.length; i++) { - try { - var ax = new(window.ActiveXObject)(axs[i]); - return function () { - if (ax) { - var ax_ = ax; - ax = null; - return ax_; - } - else { - return new(window.ActiveXObject)(axs[i]); - } - }; - } - catch (e) {} - } - throw new Error('ajax not supported in this browser') - } - else { - throw new Error('ajax not supported in this browser'); - } -})(); - -}); - -require.define("events",function(require,module,exports,__dirname,__filename,process){if (!process.EventEmitter) process.EventEmitter = function () {}; - -var EventEmitter = exports.EventEmitter = process.EventEmitter; -var isArray = typeof Array.isArray === 'function' - ? Array.isArray - : function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]' - } -; - -// By default EventEmitters will print a warning if more than -// 10 listeners are added to it. This is a useful default which -// helps finding memory leaks. -// -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -var defaultMaxListeners = 10; -EventEmitter.prototype.setMaxListeners = function(n) { - if (!this._events) this._events = {}; - this._events.maxListeners = n; -}; - - -EventEmitter.prototype.emit = function(type) { - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events || !this._events.error || - (isArray(this._events.error) && !this._events.error.length)) - { - if (arguments[1] instanceof Error) { - throw arguments[1]; // Unhandled 'error' event - } else { - throw new Error("Uncaught, unspecified 'error' event."); - } - return false; - } - } - - if (!this._events) return false; - var handler = this._events[type]; - if (!handler) return false; - - if (typeof handler == 'function') { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - var args = Array.prototype.slice.call(arguments, 1); - handler.apply(this, args); - } - return true; - - } else if (isArray(handler)) { - var args = Array.prototype.slice.call(arguments, 1); - - var listeners = handler.slice(); - for (var i = 0, l = listeners.length; i < l; i++) { - listeners[i].apply(this, args); - } - return true; - - } else { - return false; - } -}; - -// EventEmitter is defined in src/node_events.cc -// EventEmitter.prototype.emit() is also defined there. -EventEmitter.prototype.addListener = function(type, listener) { - if ('function' !== typeof listener) { - throw new Error('addListener only takes instances of Function'); - } - - if (!this._events) this._events = {}; - - // To avoid recursion in the case that type == "newListeners"! Before - // adding it to the listeners, first emit "newListeners". - this.emit('newListener', type, listener); - - if (!this._events[type]) { - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - } else if (isArray(this._events[type])) { - - // Check for listener leak - if (!this._events[type].warned) { - var m; - if (this._events.maxListeners !== undefined) { - m = this._events.maxListeners; - } else { - m = defaultMaxListeners; - } - - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - console.trace(); - } - } - - // If we've already got an array, just append. - this._events[type].push(listener); - } else { - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - var self = this; - self.on(type, function g() { - self.removeListener(type, g); - listener.apply(this, arguments); - }); - - return this; -}; - -EventEmitter.prototype.removeListener = function(type, listener) { - if ('function' !== typeof listener) { - throw new Error('removeListener only takes instances of Function'); - } - - // does not use listeners(), so no side effect of creating _events[type] - if (!this._events || !this._events[type]) return this; - - var list = this._events[type]; - - if (isArray(list)) { - var i = list.indexOf(listener); - if (i < 0) return this; - list.splice(i, 1); - if (list.length == 0) - delete this._events[type]; - } else if (this._events[type] === listener) { - delete this._events[type]; - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - // does not use listeners(), so no side effect of creating _events[type] - if (type && this._events && this._events[type]) this._events[type] = null; - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - if (!this._events) this._events = {}; - if (!this._events[type]) this._events[type] = []; - if (!isArray(this._events[type])) { - this._events[type] = [this._events[type]]; - } - return this._events[type]; -}; - -}); - -require.define("/node_modules/http-browserify/lib/request.js",function(require,module,exports,__dirname,__filename,process){var EventEmitter = require('events').EventEmitter; -var Response = require('./response'); -var concatStream = require('concat-stream') - -var Request = module.exports = function (xhr, params) { - var self = this; - self.xhr = xhr; - self.body = concatStream() - - var uri = params.host + ':' + params.port + (params.path || '/'); - - xhr.open( - params.method || 'GET', - (params.scheme || 'http') + '://' + uri, - true - ); - - if (params.headers) { - Object.keys(params.headers).forEach(function (key) { - if (!self.isSafeRequestHeader(key)) return; - var value = params.headers[key]; - if (Array.isArray(value)) { - value.forEach(function (v) { - xhr.setRequestHeader(key, v); - }); - } - else xhr.setRequestHeader(key, value) - }); - } - - var res = new Response; - res.on('ready', function () { - self.emit('response', res); - }); - - xhr.onreadystatechange = function () { - res.handle(xhr); - }; -}; - -Request.prototype = new EventEmitter; - -Request.prototype.setHeader = function (key, value) { - if ((Array.isArray && Array.isArray(value)) - || value instanceof Array) { - for (var i = 0; i < value.length; i++) { - this.xhr.setRequestHeader(key, value[i]); - } - } - else { - this.xhr.setRequestHeader(key, value); - } -}; - -Request.prototype.write = function (s) { - this.body.write(s); -}; - -Request.prototype.end = function (s) { - if (s !== undefined) this.body.write(s); - this.body.end() - this.xhr.send(this.body.getBody()); -}; - -// Taken from http://dxr.mozilla.org/mozilla/mozilla-central/content/base/src/nsXMLHttpRequest.cpp.html -Request.unsafeHeaders = [ - "accept-charset", - "accept-encoding", - "access-control-request-headers", - "access-control-request-method", - "connection", - "content-length", - "cookie", - "cookie2", - "content-transfer-encoding", - "date", - "expect", - "host", - "keep-alive", - "origin", - "referer", - "te", - "trailer", - "transfer-encoding", - "upgrade", - "user-agent", - "via" -]; - -Request.prototype.isSafeRequestHeader = function (headerName) { - if (!headerName) return false; - return (Request.unsafeHeaders.indexOf(headerName.toLowerCase()) === -1) -}; - -}); - -require.define("/node_modules/http-browserify/lib/response.js",function(require,module,exports,__dirname,__filename,process){var EventEmitter = require('events').EventEmitter; - -var Response = module.exports = function (res) { - this.offset = 0; -}; - -Response.prototype = new EventEmitter; - -var capable = { - streaming : true, - status2 : true -}; - -function parseHeaders (res) { - var lines = res.getAllResponseHeaders().split(/\r?\n/); - var headers = {}; - for (var i = 0; i < lines.length; i++) { - var line = lines[i]; - if (line === '') continue; - - var m = line.match(/^([^:]+):\s*(.*)/); - if (m) { - var key = m[1].toLowerCase(), value = m[2]; - - if (headers[key] !== undefined) { - if ((Array.isArray && Array.isArray(headers[key])) - || headers[key] instanceof Array) { - headers[key].push(value); - } - else { - headers[key] = [ headers[key], value ]; - } - } - else { - headers[key] = value; - } - } - else { - headers[line] = true; - } - } - return headers; -} - -Response.prototype.getResponse = function (xhr) { - var respType = xhr.responseType.toLowerCase(); - if (respType === "blob") return xhr.responseBlob; - if (respType === "arraybuffer") return xhr.response; - return xhr.responseText; -} - -Response.prototype.getHeader = function (key) { - return this.headers[key.toLowerCase()]; -}; - -Response.prototype.handle = function (res) { - if (res.readyState === 2 && capable.status2) { - try { - this.statusCode = res.status; - this.headers = parseHeaders(res); - } - catch (err) { - capable.status2 = false; - } - - if (capable.status2) { - this.emit('ready'); - } - } - else if (capable.streaming && res.readyState === 3) { - try { - if (!this.statusCode) { - this.statusCode = res.status; - this.headers = parseHeaders(res); - this.emit('ready'); - } - } - catch (err) {} - - try { - this.write(res); - } - catch (err) { - capable.streaming = false; - } - } - else if (res.readyState === 4) { - if (!this.statusCode) { - this.statusCode = res.status; - this.emit('ready'); - } - this.write(res); - - if (res.error) { - this.emit('error', this.getResponse(res)); - } - else this.emit('end'); - } -}; - -Response.prototype.write = function (res) { - var respBody = this.getResponse(res); - if (respBody.toString().match(/ArrayBuffer/)) { - this.emit('data', new Uint8Array(respBody, this.offset)); - this.offset = respBody.byteLength; - return; - } - if (respBody.length > this.offset) { - this.emit('data', respBody.slice(this.offset)); - this.offset = respBody.length; - } -}; - -}); - -require.define("/node_modules/http-browserify/node_modules/concat-stream/package.json",function(require,module,exports,__dirname,__filename,process){module.exports = {} -}); - -require.define("/node_modules/http-browserify/node_modules/concat-stream/index.js",function(require,module,exports,__dirname,__filename,process){var stream = require('stream') -var util = require('util') - -function ConcatStream(cb) { - stream.Stream.call(this) - this.writable = true - if (cb) this.cb = cb - this.body = [] - if (this.cb) this.on('error', cb) -} - -util.inherits(ConcatStream, stream.Stream) - -ConcatStream.prototype.write = function(chunk) { - this.body.push(chunk) -} - -ConcatStream.prototype.arrayConcat = function(arrs) { - if (arrs.length === 0) return [] - if (arrs.length === 1) return arrs[0] - return arrs.reduce(function (a, b) { return a.concat(b) }) -} - -ConcatStream.prototype.isArray = function(arr) { - var isArray = Array.isArray(arr) - var isTypedArray = arr.toString().match(/Array/) - return isArray || isTypedArray -} - -ConcatStream.prototype.getBody = function () { - if (this.body.length === 0) return - if (typeof(this.body[0]) === "string") return this.body.join('') - if (this.isArray(this.body[0])) return this.arrayConcat(this.body) - if (typeof(Buffer) !== "undefined" && Buffer.isBuffer(this.body[0])) { - return Buffer.concat(this.body) - } - return this.body -} - -ConcatStream.prototype.end = function() { - if (this.cb) this.cb(false, this.getBody()) -} - -module.exports = function(cb) { - return new ConcatStream(cb) -} - -module.exports.ConcatStream = ConcatStream - -}); - -require.define("stream",function(require,module,exports,__dirname,__filename,process){var events = require('events'); -var util = require('util'); - -function Stream() { - events.EventEmitter.call(this); -} -util.inherits(Stream, events.EventEmitter); -module.exports = Stream; -// Backwards-compat with node 0.4.x -Stream.Stream = Stream; - -Stream.prototype.pipe = function(dest, options) { - var source = this; - - function ondata(chunk) { - if (dest.writable) { - if (false === dest.write(chunk) && source.pause) { - source.pause(); - } - } - } - - source.on('data', ondata); - - function ondrain() { - if (source.readable && source.resume) { - source.resume(); - } - } - - dest.on('drain', ondrain); - - // If the 'end' option is not supplied, dest.end() will be called when - // source gets the 'end' or 'close' events. Only dest.end() once, and - // only when all sources have ended. - if (!dest._isStdio && (!options || options.end !== false)) { - dest._pipeCount = dest._pipeCount || 0; - dest._pipeCount++; - - source.on('end', onend); - source.on('close', onclose); - } - - var didOnEnd = false; - function onend() { - if (didOnEnd) return; - didOnEnd = true; - - dest._pipeCount--; - - // remove the listeners - cleanup(); - - if (dest._pipeCount > 0) { - // waiting for other incoming streams to end. - return; - } - - dest.end(); - } - - - function onclose() { - if (didOnEnd) return; - didOnEnd = true; - - dest._pipeCount--; - - // remove the listeners - cleanup(); - - if (dest._pipeCount > 0) { - // waiting for other incoming streams to end. - return; - } - - dest.destroy(); - } - - // don't leave dangling pipes when there are errors. - function onerror(er) { - cleanup(); - if (this.listeners('error').length === 0) { - throw er; // Unhandled stream error in pipe. - } - } - - source.on('error', onerror); - dest.on('error', onerror); - - // remove all the event listeners that were added. - function cleanup() { - source.removeListener('data', ondata); - dest.removeListener('drain', ondrain); - - source.removeListener('end', onend); - source.removeListener('close', onclose); - - source.removeListener('error', onerror); - dest.removeListener('error', onerror); - - source.removeListener('end', cleanup); - source.removeListener('close', cleanup); - - dest.removeListener('end', cleanup); - dest.removeListener('close', cleanup); - } - - source.on('end', cleanup); - source.on('close', cleanup); - - dest.on('end', cleanup); - dest.on('close', cleanup); - - dest.emit('pipe', source); - - // Allow for unix-like usage: A.pipe(B).pipe(C) - return dest; -}; - -}); - -require.define("util",function(require,module,exports,__dirname,__filename,process){var events = require('events'); - -exports.print = function () {}; -exports.puts = function () {}; -exports.debug = function() {}; - -exports.inspect = function(obj, showHidden, depth, colors) { - var seen = []; - - var stylize = function(str, styleType) { - // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics - var styles = - { 'bold' : [1, 22], - 'italic' : [3, 23], - 'underline' : [4, 24], - 'inverse' : [7, 27], - 'white' : [37, 39], - 'grey' : [90, 39], - 'black' : [30, 39], - 'blue' : [34, 39], - 'cyan' : [36, 39], - 'green' : [32, 39], - 'magenta' : [35, 39], - 'red' : [31, 39], - 'yellow' : [33, 39] }; - - var style = - { 'special': 'cyan', - 'number': 'blue', - 'boolean': 'yellow', - 'undefined': 'grey', - 'null': 'bold', - 'string': 'green', - 'date': 'magenta', - // "name": intentionally not styling - 'regexp': 'red' }[styleType]; - - if (style) { - return '\033[' + styles[style][0] + 'm' + str + - '\033[' + styles[style][1] + 'm'; - } else { - return str; - } - }; - if (! colors) { - stylize = function(str, styleType) { return str; }; - } - - function format(value, recurseTimes) { - // Provide a hook for user-specified inspect functions. - // Check that value is an object with an inspect function on it - if (value && typeof value.inspect === 'function' && - // Filter out the util module, it's inspect function is special - value !== exports && - // Also filter out any prototype objects using the circular check. - !(value.constructor && value.constructor.prototype === value)) { - return value.inspect(recurseTimes); - } - - // Primitive types cannot have properties - switch (typeof value) { - case 'undefined': - return stylize('undefined', 'undefined'); - - case 'string': - var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') - .replace(/'/g, "\\'") - .replace(/\\"/g, '"') + '\''; - return stylize(simple, 'string'); - - case 'number': - return stylize('' + value, 'number'); - - case 'boolean': - return stylize('' + value, 'boolean'); - } - // For some reason typeof null is "object", so special case here. - if (value === null) { - return stylize('null', 'null'); - } - - // Look up the keys of the object. - var visible_keys = Object_keys(value); - var keys = showHidden ? Object_getOwnPropertyNames(value) : visible_keys; - - // Functions without properties can be shortcutted. - if (typeof value === 'function' && keys.length === 0) { - if (isRegExp(value)) { - return stylize('' + value, 'regexp'); - } else { - var name = value.name ? ': ' + value.name : ''; - return stylize('[Function' + name + ']', 'special'); - } - } - - // Dates without properties can be shortcutted - if (isDate(value) && keys.length === 0) { - return stylize(value.toUTCString(), 'date'); - } - - var base, type, braces; - // Determine the object type - if (isArray(value)) { - type = 'Array'; - braces = ['[', ']']; - } else { - type = 'Object'; - braces = ['{', '}']; - } - - // Make functions say that they are functions - if (typeof value === 'function') { - var n = value.name ? ': ' + value.name : ''; - base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']'; - } else { - base = ''; - } - - // Make dates with properties first say the date - if (isDate(value)) { - base = ' ' + value.toUTCString(); - } - - if (keys.length === 0) { - return braces[0] + base + braces[1]; - } - - if (recurseTimes < 0) { - if (isRegExp(value)) { - return stylize('' + value, 'regexp'); - } else { - return stylize('[Object]', 'special'); - } - } - - seen.push(value); - - var output = keys.map(function(key) { - var name, str; - if (value.__lookupGetter__) { - if (value.__lookupGetter__(key)) { - if (value.__lookupSetter__(key)) { - str = stylize('[Getter/Setter]', 'special'); - } else { - str = stylize('[Getter]', 'special'); - } - } else { - if (value.__lookupSetter__(key)) { - str = stylize('[Setter]', 'special'); - } - } - } - if (visible_keys.indexOf(key) < 0) { - name = '[' + key + ']'; - } - if (!str) { - if (seen.indexOf(value[key]) < 0) { - if (recurseTimes === null) { - str = format(value[key]); - } else { - str = format(value[key], recurseTimes - 1); - } - if (str.indexOf('\n') > -1) { - if (isArray(value)) { - str = str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n').substr(2); - } else { - str = '\n' + str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n'); - } - } - } else { - str = stylize('[Circular]', 'special'); - } - } - if (typeof name === 'undefined') { - if (type === 'Array' && key.match(/^\d+$/)) { - return str; - } - name = JSON.stringify('' + key); - if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { - name = name.substr(1, name.length - 2); - name = stylize(name, 'name'); - } else { - name = name.replace(/'/g, "\\'") - .replace(/\\"/g, '"') - .replace(/(^"|"$)/g, "'"); - name = stylize(name, 'string'); - } - } - - return name + ': ' + str; - }); - - seen.pop(); - - var numLinesEst = 0; - var length = output.reduce(function(prev, cur) { - numLinesEst++; - if (cur.indexOf('\n') >= 0) numLinesEst++; - return prev + cur.length + 1; - }, 0); - - if (length > 50) { - output = braces[0] + - (base === '' ? '' : base + '\n ') + - ' ' + - output.join(',\n ') + - ' ' + - braces[1]; - - } else { - output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; - } - - return output; - } - return format(obj, (typeof depth === 'undefined' ? 2 : depth)); -}; - - -function isArray(ar) { - return ar instanceof Array || - Array.isArray(ar) || - (ar && ar !== Object.prototype && isArray(ar.__proto__)); -} - - -function isRegExp(re) { - return re instanceof RegExp || - (typeof re === 'object' && Object.prototype.toString.call(re) === '[object RegExp]'); -} - - -function isDate(d) { - if (d instanceof Date) return true; - if (typeof d !== 'object') return false; - var properties = Date.prototype && Object_getOwnPropertyNames(Date.prototype); - var proto = d.__proto__ && Object_getOwnPropertyNames(d.__proto__); - return JSON.stringify(proto) === JSON.stringify(properties); -} - -function pad(n) { - return n < 10 ? '0' + n.toString(10) : n.toString(10); -} - -var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', - 'Oct', 'Nov', 'Dec']; - -// 26 Feb 16:19:34 -function timestamp() { - var d = new Date(); - var time = [pad(d.getHours()), - pad(d.getMinutes()), - pad(d.getSeconds())].join(':'); - return [d.getDate(), months[d.getMonth()], time].join(' '); -} - -exports.log = function (msg) {}; - -exports.pump = null; - -var Object_keys = Object.keys || function (obj) { - var res = []; - for (var key in obj) res.push(key); - return res; -}; - -var Object_getOwnPropertyNames = Object.getOwnPropertyNames || function (obj) { - var res = []; - for (var key in obj) { - if (Object.hasOwnProperty.call(obj, key)) res.push(key); - } - return res; -}; - -var Object_create = Object.create || function (prototype, properties) { - // from es5-shim - var object; - if (prototype === null) { - object = { '__proto__' : null }; - } - else { - if (typeof prototype !== 'object') { - throw new TypeError( - 'typeof prototype[' + (typeof prototype) + '] != \'object\'' - ); - } - var Type = function () {}; - Type.prototype = prototype; - object = new Type(); - object.__proto__ = prototype; - } - if (typeof properties !== 'undefined' && Object.defineProperties) { - Object.defineProperties(object, properties); - } - return object; -}; - -exports.inherits = function(ctor, superCtor) { - ctor.super_ = superCtor; - ctor.prototype = Object_create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); -}; - -}); - -require.define("/config.js",function(require,module,exports,__dirname,__filename,process){// jshint settings -/*global exports: false */ - -exports.host = '127.0.0.1'; -exports.port = 5984; -exports.username = ''; -exports.password = ''; -exports.secure = false; -exports.path = ''; - -}); - -require.define("/database.js",function(require,module,exports,__dirname,__filename,process){// jshint settings -/*global require: false, exports: false */ - -var querystring = require('querystring'), - Document = require('./document.js').Document, - Design = require('./design.js').Design; - - -/** - * database object - * - * @constructor - * @param {string} name of the database - * @param {cushion.Connection} connection connection object - */ -var Database = function(name, connection) { - this._name = name; - this._connection = connection; -}; - - -/** - * getting all documents of the database, because this is a special couchdb view - * you can use the same query parameters like at normal views - * - * @param {object|function(error, info, documents)} paramsOrCallback query - * parameters for the view - * @param {?function(error, info, object)} callback function that - * will be called, after getting response from the view, or if there was an - * error - */ -Database.prototype.allDocuments = function(paramsOrCallback, callback) { - var params = (typeof(paramsOrCallback) === 'object') ? - '?' + querystring.stringify(paramsOrCallback, '&', '=') : - ''; - callback = callback || paramsOrCallback; - - this._connection.request({ - 'method': 'GET', - 'path': this.name() + '/_all_docs' + params, - 'callback': (function(error, response) { - var info, - documents = {}, - i; - - if (error === null) { - info = { - 'total': response.total_rows, - 'offset': response.offset - }; - - for (i = 0; response.rows[i]; ++i) { - documents[response.rows[i].id] = response.rows[i].value.rev; - } - } - - callback(error, info, documents); - }).bind(this) - }); -}; - - -/** - * cleanup views - * - * @param {function(error, started)} callback function that will be called, - * after cleanup was started or if there was an error - */ -Database.prototype.cleanup = function(callback) { - this._connection.request({ - 'method': 'POST', - 'path': this.name() + '/_view_cleanup', - 'callback': function(error, response) { - callback(error, (response) ? true : null); - } - }); -}; - - -/** - * compacts the database or specific view - * - * @param {string} designOrCallback name of a design if you only want to compact - * a view, or function that will be called, after compaction was started of - * if there was an error - * @param {?function(error, started)} callback function that will be called, - * after compaction was started or if there was an error - */ -Database.prototype.compact = function(designOrCallback, callback) { - var design = (callback) ? designOrCallback : undefined; - callback = callback || designOrCallback; - - this._connection.request({ - 'method': 'POST', - 'path': this.name() + '/_compact' + ((design) ? '/' + design : ''), - 'callback': (function(error, response) { - callback(error, (response) ? true : null); - }).bind(this) - }); -}; - - -/** - * create the database - * - * @param {function(error, confirm)} callback function that will be called, - * after creating the database, or if there was an error - */ -Database.prototype.create = function(callback) { - this._connection.request({ - 'method': 'PUT', - 'path': this.name(), - 'callback': (function(error, response) { - if (error === null && response.ok === true) { - response = true; - } - - callback(error, response); - }).bind(this) - }); -}; - - -/** - * delete the database - * - * @param {function(error, deleted)} callback function that will be called, - * after deleting the database, or if there was an error - */ -Database.prototype.destroy = function(callback) { - this._connection.request({ - 'method': 'DELETE', - 'path': this.name() , - 'callback': function(error, response) { - if (response && response.ok === true) { - response = true; - } - - callback(error, response); - } - }); -}; - - -/** - * gets a document object - * - * @param {?string} docId id of the couch document - * @param {?string} revision revision of the document - * @return {cushion.Document} the document object - */ -Database.prototype.document = function(docId, revision) { - var Doc = (docId && docId.match(/^_design\//)) ? Design : Document; - - return new Doc( - docId || null, - revision || null, - this._connection, - this - ); -}; - - -/** - * check if database exists - * - * @param {function(error, exists)} callback function that will be called, after - * getting the information database exists or not, of if there was an error - */ -Database.prototype.exists = function(callback) { - this._connection.request({ - 'method': 'GET', - 'path': this._name, - 'callback': function(error, response) { - var exists = true; - - if (error && error.error === 'not_found') { - error = null; - exists = false; - } - - callback(error, (error === null) ? exists : null); - } - }); -}; - - -/** - * gets infos about the database - * - * @param {function(error, info)} callback function that will be called, after - * getting the informations, or if there was an error - */ -Database.prototype.info = function(callback) { - this._connection.request({ - 'method': 'GET', - 'path': this._name, - 'callback': callback - }); -}; - - -/** - * requests a list - * - * @param {string} design name of the design document, after the '_design/' - * @param {string} list name of the list function - * @param {string} viewOrOtherDesign name of the view, or name of another design - * document, which holds the view function - * @param {string|object|function(error, response)} viewOrParamsOrCallback name - * of the view function, or an object which holds query parameters for the - * request or function that will be called, after getting a response or if - * there was an error - * @param {?object|function(error, response)} paramsOrCallback an object with - * key-value-pairs that holds query parameters for the request, or function - * that will be called, after getting a response, or if there was an error - * @param {?function(error, response)} callback function that will be called, - * after getting a response or if there was an error - */ -Database.prototype.list = function( - design, - list, - viewOrOtherDesign, - viewOrParamsOrCallback, - paramsOrCallback, - callback -) { - var params = (typeof(viewOrParamsOrCallback) === 'object') ? - '?' + querystring.stringify(viewOrParamsOrCallback, '&', '=') : - (typeof(paramsOrCallback) === 'object') ? - '?' + querystring.stringify(paramsOrCallback, '&', '=') : - '', - view = (typeof(viewOrParamsOrCallback) === 'string') ? - viewOrParamsOrCallback : - viewOrOtherDesign, - otherDesign = (typeof(viewOrParamsOrCallback) === 'string') ? - '/' + viewOrOtherDesign : - '', - path = this.name() + '/_design/' + design + '/_list/' + list + - otherDesign + '/' + view + params; - callback = callback || paramsOrCallback || viewOrParamsOrCallback; - - this._connection.request({ - 'method': 'GET', - 'path': path, - 'callback': callback - }); -}; - - -/** - * gets name of this database - * - * @return {string} name of this database - */ -Database.prototype.name = function() { - return this._name; -}; - - -/** - * sets or gets the document revision limit - * if you set two arguments (limit and callback) it will use as a setter - * only with one argument (callback) it's a getter - * - * @param {number|function(error, limit)} limitOrCallback positive integer as a - * new setting for the revision limit or function that will be called, after - * getting the revision limit or if there was an error - * @param {?function(error, saved)} callback function that will be called, after - * setting the new revision limit or if there was an error - */ -Database.prototype.revisionLimit = function(limitOrCallback, callback) { - var limit = (callback) ? limitOrCallback : null, - options = { - 'method': (limit !== null) ? 'PUT' : 'GET', - 'path': this._name + '/_revs_limit' - }; - callback = callback || limitOrCallback; - - if (limit !== null) { - options.body = '' + limit; - } - - options.callback = function(error, response) { - if (error) { - callback(error, null); - } else if (limit === null) { - callback(null, response); - } else { - callback(null, true); - } - }; - - this._connection.request(options); -}; - - -/** - * retrieving a show function - * - * @param {string} design name of the design document, after the '_design/', - * @param {string} show name of the show function - * @param {string|object|function(error, result)} docIdOrQueryOrCallback id of - * the document or additional query params for the show function, or - * function that will be called after getting a result or if there was an - * error - * @param {?object|function(error, result)} queryOrCallback additional query - * params for the show function, or function that will be called after - * getting a result or if there was an error - * @param {?function(error, result)} callback function that will be called after - * getting a result or if there was an error - */ -Database.prototype.show = function( - design, - show, - docIdOrQueryOrCallback, - queryOrCallback, - callback -) { - var docId = (typeof(docIdOrQueryOrCallback) === 'string') ? - '/' + docIdOrQueryOrCallback : - '', - query = ''; - callback = callback || queryOrCallback || docIdOrQueryOrCallback; - - if (typeof(docIdOrQueryOrCallback) === 'object') { - query = '?' + querystring.stringify(docIdOrQueryOrCallback, '&', '='); - } else if (typeof(queryOrCallback) === 'object') { - query = '?' + querystring.stringify(queryOrCallback, '&', '='); - } - - this._connection.request({ - 'method': 'GET', - 'path': this._name + - '/_design/' + design + - '/_show/' + show + - docId + query, - 'callback': callback - }); -}; - - -/** - * requests a temporary view - * - * @param {string} map map function for the view as a string not as a function - * @param {string|function(error, info, rows)} reduceOrCallback reduce function - * for the view as a string not as a function or function that will be - * called after retrieving the view or if there was an error - * @param {?function(error, info, rows)} callback function that will be called, - * after retrieving the view or if there was an error - */ -Database.prototype.temporaryView = function( - map, - reduceOrParamsOrCallback, - paramsOrCallback, - callback -) { - var reduce = (typeof(reduceOrParamsOrCallback) === 'string') ? - reduceOrParamsOrCallback : - null, - params = (typeof(reduceOrParamsOrCallback) === 'object') ? - reduceOrParamsOrCallback : - paramsOrCallback, - body = {'map': map}; - callback = callback || paramsOrCallback || reduceOrParamsOrCallback; - params = querystring.stringify(params, '&', '='); - - if (reduce !== null) { - body.reduce = reduce; - } - - this._connection.request({ - 'method': 'POST', - 'path': this.name() + '/_temp_view' + ((params) ? '?' + params : ''), - 'body': body, - 'callback': function(error, response) { - var info = null, - rows = null; - - if (error === null) { - info = { - 'total': response.total_rows, - 'offset': response.offset - }; - - rows = response.rows - } - - callback(error, info, rows); - } - }); -}; - - -/** - * requests a view - * - * @param {string} design name of the design document, after the '_design/' - * @param {string} view name of the view - * @param {object|function(error, info, rows)} paramsOrCallback query - * parameters for the view, or function that will be call, after getting - * response from the view, or if there was an error - * @param {?function(error, info, rows)} callback function that will be - * called, after getting response from the view, or if there was an error - */ -Database.prototype.view = function(design, view, paramsOrCallback, callback) { - var params = (typeof(paramsOrCallback) === 'object') ? - '?' + querystring.stringify(paramsOrCallback, '&', '=') : - '', - path = this.name() + '/_design/' + design + '/_view/' + view; - callback = callback || paramsOrCallback; - - this._connection.request({ - 'method': 'GET', - 'path': path + params, - 'callback': (function(error, response) { - var info = null, - rows = null; - - if (error === null) { - info = { - 'total': response.total_rows, - 'offset': response.offset - }; - - rows = response.rows; - } - - callback(error, info, rows); - }).bind(this) - }); -}; - - -exports.Database = Database; -}); - -require.define("querystring",function(require,module,exports,__dirname,__filename,process){var isArray = typeof Array.isArray === 'function' - ? Array.isArray - : function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]' - }; - -var objectKeys = Object.keys || function objectKeys(object) { - if (object !== Object(object)) throw new TypeError('Invalid object'); - var keys = []; - for (var key in object) if (object.hasOwnProperty(key)) keys[keys.length] = key; - return keys; -} - - -/*! - * querystring - * Copyright(c) 2010 TJ Holowaychuk - * MIT Licensed - */ - -/** - * Library version. - */ - -exports.version = '0.3.1'; - -/** - * Object#toString() ref for stringify(). - */ - -var toString = Object.prototype.toString; - -/** - * Cache non-integer test regexp. - */ - -var notint = /[^0-9]/; - -/** - * Parse the given query `str`, returning an object. - * - * @param {String} str - * @return {Object} - * @api public - */ - -exports.parse = function(str){ - if (null == str || '' == str) return {}; - - function promote(parent, key) { - if (parent[key].length == 0) return parent[key] = {}; - var t = {}; - for (var i in parent[key]) t[i] = parent[key][i]; - parent[key] = t; - return t; - } - - return String(str) - .split('&') - .reduce(function(ret, pair){ - try{ - pair = decodeURIComponent(pair.replace(/\+/g, ' ')); - } catch(e) { - // ignore - } - - var eql = pair.indexOf('=') - , brace = lastBraceInKey(pair) - , key = pair.substr(0, brace || eql) - , val = pair.substr(brace || eql, pair.length) - , val = val.substr(val.indexOf('=') + 1, val.length) - , parent = ret; - - // ?foo - if ('' == key) key = pair, val = ''; - - // nested - if (~key.indexOf(']')) { - var parts = key.split('[') - , len = parts.length - , last = len - 1; - - function parse(parts, parent, key) { - var part = parts.shift(); - - // end - if (!part) { - if (isArray(parent[key])) { - parent[key].push(val); - } else if ('object' == typeof parent[key]) { - parent[key] = val; - } else if ('undefined' == typeof parent[key]) { - parent[key] = val; - } else { - parent[key] = [parent[key], val]; - } - // array - } else { - obj = parent[key] = parent[key] || []; - if (']' == part) { - if (isArray(obj)) { - if ('' != val) obj.push(val); - } else if ('object' == typeof obj) { - obj[objectKeys(obj).length] = val; - } else { - obj = parent[key] = [parent[key], val]; - } - // prop - } else if (~part.indexOf(']')) { - part = part.substr(0, part.length - 1); - if(notint.test(part) && isArray(obj)) obj = promote(parent, key); - parse(parts, obj, part); - // key - } else { - if(notint.test(part) && isArray(obj)) obj = promote(parent, key); - parse(parts, obj, part); - } - } - } - - parse(parts, parent, 'base'); - // optimize - } else { - if (notint.test(key) && isArray(parent.base)) { - var t = {}; - for(var k in parent.base) t[k] = parent.base[k]; - parent.base = t; - } - set(parent.base, key, val); - } - - return ret; - }, {base: {}}).base; -}; - -/** - * Turn the given `obj` into a query string - * - * @param {Object} obj - * @return {String} - * @api public - */ - -var stringify = exports.stringify = function(obj, prefix) { - if (isArray(obj)) { - return stringifyArray(obj, prefix); - } else if ('[object Object]' == toString.call(obj)) { - return stringifyObject(obj, prefix); - } else if ('string' == typeof obj) { - return stringifyString(obj, prefix); - } else { - return prefix; - } -}; - -/** - * Stringify the given `str`. - * - * @param {String} str - * @param {String} prefix - * @return {String} - * @api private - */ - -function stringifyString(str, prefix) { - if (!prefix) throw new TypeError('stringify expects an object'); - return prefix + '=' + encodeURIComponent(str); -} - -/** - * Stringify the given `arr`. - * - * @param {Array} arr - * @param {String} prefix - * @return {String} - * @api private - */ - -function stringifyArray(arr, prefix) { - var ret = []; - if (!prefix) throw new TypeError('stringify expects an object'); - for (var i = 0; i < arr.length; i++) { - ret.push(stringify(arr[i], prefix + '[]')); - } - return ret.join('&'); -} - -/** - * Stringify the given `obj`. - * - * @param {Object} obj - * @param {String} prefix - * @return {String} - * @api private - */ - -function stringifyObject(obj, prefix) { - var ret = [] - , keys = objectKeys(obj) - , key; - for (var i = 0, len = keys.length; i < len; ++i) { - key = keys[i]; - ret.push(stringify(obj[key], prefix - ? prefix + '[' + encodeURIComponent(key) + ']' - : encodeURIComponent(key))); - } - return ret.join('&'); -} - -/** - * Set `obj`'s `key` to `val` respecting - * the weird and wonderful syntax of a qs, - * where "foo=bar&foo=baz" becomes an array. - * - * @param {Object} obj - * @param {String} key - * @param {String} val - * @api private - */ - -function set(obj, key, val) { - var v = obj[key]; - if (undefined === v) { - obj[key] = val; - } else if (isArray(v)) { - v.push(val); - } else { - obj[key] = [v, val]; - } -} - -/** - * Locate last brace in `str` within the key. - * - * @param {String} str - * @return {Number} - * @api private - */ - -function lastBraceInKey(str) { - var len = str.length - , brace - , c; - for (var i = 0; i < len; ++i) { - c = str[i]; - if (']' == c) brace = false; - if ('[' == c) brace = true; - if ('=' == c && !brace) return i; - } -} - -}); - -require.define("/document.js",function(require,module,exports,__dirname,__filename,process){// jshint settings -/*global require: false, exports: false, process: false */ - -var fs = require('fs'); - - -/** - * document object - * - * @constructor - * @param {string|null} id string if you have document id, null if not - * @param {cushion.Connection} connection cushion connection object - * @param {cushion.Database} database cushion database object - */ -var Document = function(id, revision, connection, database) { - this._id = id; - this._revision = revision; - this._connection = connection; - this._database = database; - this._body = {}; - - this._error = { - 'noId': 'no document id was set', - 'noRevision': 'no revision was set', - 'noFile': 'could not read file' - }; -}; - - -/** - * gets the body of the document or saves data to it - * if you want to save data, you can set one argument for each child, e.g. - * .body('foo', 'bar', 'foobar'); that means you set foo.bar to 'foobar' - * if there are is no foo.bar it will be created - * if you set the body and the content argument (the last one) was explicitly - * set to 'undefined', the property will be deleted - * - * @return {object|cushion.Document} get a deep copy of the document body, or - * the document, if you save data to the body - */ -Document.prototype.body = function() { - var obj = Array.prototype.slice.call(arguments), - data = obj.splice(obj.length - 1, 1)[0], - path = this._body, - returnData; - - if (obj && obj.length > 0 && arguments.length > 1) { - // go through arguments list to set body members - obj.forEach(function(name, index, array) { - if (index === array.length - 1 && typeof(data) === 'undefined') { - delete path[name]; - } else { - path[name] = (index === array.length - 1) ? data : path[name] || {}; - path = path[name]; - } - }); - - returnData = this; - } else if (obj && arguments.length > 0) { - if (typeof(data) === 'object') { - // we want to set the complete body - this._body = JSON.parse(JSON.stringify(data)); - - returnData = this; - } else { - // we don't set anything, but we want a specific body property - returnData = (typeof(this._body[data]) === 'object') ? - JSON.parse(JSON.stringify(this._body[data])) : - this._body[data]; - } - } else { - // we don't set anything, but we want the complete body - returnData = JSON.parse(JSON.stringify(this._body)); - } - - return returnData; -}; - - -/** - * copy a document, the document id have to set before, first document at the - * callback is the current document, second document is the target document - * - * @param {string} targetId target document id - * @param {string|function(error, cushion.Document, cushion.Document)} - * targetRevisionOrCallback copy to a specific document revision, or - * function that will be called, after copying the document or if there was - * error - * @param {?function(error, cushion.Document, cushion.Document)} callback - * function that will be called copying the document or if there was an - * error - */ -Document.prototype.copy = function( - targetId, - targetRevisionOrCallback, - callback -) { - var targetRevision = (callback) ? '?rev=' + targetRevisionOrCallback : ''; - callback = callback || targetRevisionOrCallback; - - if (this._id === null) { - process.nextTick(callback( - {'error': 'no_copy', 'reason': this._error.noId}, - null, - null - )); - } else { - this._connection.request({ - 'method': 'COPY', - 'headers': {'Destination': targetId + targetRevision}, - 'path': this._database.name() + '/' + - this._id + - ((this._revision) ? '?rev=' + this._revision : ''), - 'callback': (function(error, response) { - if (response) { - response = this._database.document(response.id, response.rev); - } - - callback(error, this, response); - }).bind(this) - }); - } -}; - - -/** - * deletes an attachment - * - * @param {string} name attachment name - * @param {function(error, deleted)} callback function that will be called, - * after the attachment was deleted - */ -Document.prototype.deleteAttachment = function(name, callback) { - this._connection.request({ - 'method': 'DELETE', - 'path': this._database.name() + '/' + - this._id + '/' + name + - '?rev=' + this._revision, - 'callback': (function(error, confirmed) { - if (error) { - confirmed = false; - } else { - this._revision = confirmed.rev; - confirmed = true; - } - - callback(error, confirmed); - }).bind(this) - }); -}; - - -/** - * delete the document, the id and revision have to set before, without it you - * will get an error - * - * @param {function(error, cushion.Document)} callback function that will be - * called, after deleting the document, or if there was an error - */ -Document.prototype.destroy = function(callback) { - if (this._id === null) { - process.nextTick(callback( - {'error': 'no_delete', 'reason': this._error.noId}, - null - )); - } else if (this._revision === null) { - process.nextTick(callback( - {'error': 'no_delete', 'reason': this._error.noRevision}, - null - )); - } else { - this._connection.request({ - 'method': 'DELETE', - 'path': this._database.name() + '/' + this._id + '?rev=' + this._revision, - 'callback': (function(error, response) { - if (response) { - this._revision = response.rev; - } - - callback(error, this); - }).bind(this) - }); - } -}; - - -/** - * load an attachment - * - * @param {string} name attachment name - * @param {function(error, attachment)} callback function that will be called, - * after the attachment was loaded - */ -Document.prototype.getAttachment = function(name, callback) { - this._connection.request({ - 'method': 'GET', - 'path': this._database.name() + '/' + - this._id + '/' + name + - '?rev=' + this._revision, - 'callback': callback - }); -}; - - -/** - * get the id of the document - * - * @return {string} id of document - */ -Document.prototype.id = function() { - return this._id; -}; - - -/** - * info about the document - * - * @param {function(error, info)} callback function that will called, after - * retrieving information, or if there was an error - */ -Document.prototype.info = function(callback) { - if (this._id === null) { - process.nextTick(callback( - {'error': 'no_info', 'reason': 'no document id was set'}, - null - )); - } else { - this._connection.request({ - 'method': 'HEAD', - 'path': this._database.name() + '/' + this._id, - 'callback': (function(error, response, headers) { - var info = null; - - if (error === null) { - this._revision = headers.etag.substr(1, headers.etag.length - 2); - - info = { - 'revision': this._revision, - 'size': headers['content-length'] - }; - } - - callback(error, info); - }).bind(this) - }); - } -}; - - -/** - * loads the document, the id have to set before, without it you will get an - * error - * - * @param {function(error, cushion.Document)} callback function that will be - * called, after loading the document or if there was an error - */ -Document.prototype.load = function(callback) { - if (this._id === null) { - process.nextTick(callback( - {'error': 'no_load', 'reason': this._error.noId}, - null - )); - } else { - this._connection.request({ - 'method': 'GET', - 'path': this._database.name() + '/' + - this._id + - ((this._revision !== null) ? '?rev=' + this._revision : ''), - 'callback': (function(error, response) { - if (error === null) { - // get document content - this._saveContent(response); - } - - callback(error, this); - }).bind(this) - }); - } -}; - - -/** - * get the revision of the document - * - * @return {string} revision of the document - */ -Document.prototype.revision = function() { - return this._revision; -}; - - -/** - * saves content at the document - * try to creates a new document, if there's no revision - * if you want to save an existing document, you have to .load() it before, so - * the revision id will be saved here - * - * @param {function(error, cushion.Document)} callback function that will be - * called, after saving the new content or if there was an error - */ -Document.prototype.save = function(callback) { - var body = JSON.parse(JSON.stringify(this._body)); - - if (this._revision !== null) { - body._rev = this._revision; - } - - this._connection.request({ - 'method': (this._id === null) ? 'POST' : 'PUT', - 'path': this._database.name() + ((this._id === null) ? '' : '/' + this._id), - 'body': body, - 'callback': (function (error, response) { - if (error === null) { - this._id = response.id; - this._revision = response.rev; - } - - callback(error, this); - }).bind(this) - }); -}; - - -/** - * saves an attachment - * - * @param {string} file path to the file - * @param {string} contentType content type header of the file (e.g. text/plain) - * @param {string|function(error, response)} name of the attachment or function - * that will be called, after saving the attachment; if you don't set the - * name, it will be automatically the name of the file - * @param {?function(error, response)} callback function that will be called, - * after saving the attachment - */ -Document.prototype.saveAttachment = function( - file, - contentType, - nameOrCallback, - callback -) { - var filename = (typeof(nameOrCallback) === 'string') ? - nameOrCallback : - file.split('/').pop(); - callback = callback || nameOrCallback; - - fs.readFile(file, 'utf8', (function(error, data) { - if (error) { - process.nextTick(callback({ - 'error': 'no_file', - 'reason': this._error.noFile + ': ' + file - }, null)); - } else { - this._connection.request({ - 'method': 'PUT', - 'path': this._database.name() + '/' + - this._id + '/' + filename + - '?rev=' + this._revision, - 'headers': { - 'Content-Length': data.length, - 'Content-Type': contentType - }, - 'body': data, - 'callback': (function(error, confirmed) { - if (error) { - confirmed = false; - } else { - this._revision = confirmed.rev; - confirmed = true; - } - - callback(error, confirmed); - }).bind(this) - }); - } - }).bind(this)); -}; - - -/** - * saves the content of a whole document response - * - * @param {object} body content of the document - */ -Document.prototype._saveContent = function(body) { - var key; - body = JSON.parse(JSON.stringify(body)); - - this._body = {}; - - for (key in body) { - if (key[0] === '_') { - if (key === '_rev') { - this._revision = body[key]; - } - } else { - this._body[key] = body[key]; - } - } -}; - - -exports.Document = Document; -}); - -require.define("fs",function(require,module,exports,__dirname,__filename,process){// nothing to see here... no file methods for the browser - -}); - -require.define("/design.js",function(require,module,exports,__dirname,__filename,process){// jshint settings -/*global require: false, exports: false */ - -var util = require('util'), - Document = require('./document.js').Document; - - -/** - * design document object - * - * @constructor - * @param {string|null} id string if you have document id, null if not - * @param {cushion.Connection} connection cushion connection object - * @param {cushion.Database} database cushion database object - */ -var Design = function(id, revision, connection, database) { - Document.call(this, id, revision, connection, database); -}; - -util.inherits(Design, Document); - - -/** - * compacts the design document - * - * @param {function(error, started)} callback function that will be called, - * after compaction was started or if there was an error - */ -Design.prototype.compact = function(callback) { - this._database.compact(this._id.substr(8), callback); -}; - - -/** - * get, create, update or delete a list function - * - * @param {string} name name of the list function - * @param {?string} content string representation of the list function; if you - * set this to null, the list function will be deleted - * @return {cushion.Design|string} if you save a list function, you will get - * this design document, otherwise the string representation of the specific - * list function - */ -Design.prototype.list = function(name, content) { - if (content) { - this.body('lists', name, ((content === null) ? undefined : content)); - } - - return ((content !== undefined) ? - this : - (this._body.lists) ? this._body.lists[name] : undefined - ); -}; - - -/** - * get, create, update or delete a show function - * - * @param {string} name name of the show function - * @param {?string} content string representation of the show function; if you - * set this to null, the show function will be deleted - * @return {cushion.Design|string} if you save a show function, you will get - * this design document, otherwise the string representation of the specific - * show function - */ -Design.prototype.show = function(name, content) { - if (typeof(content) !== undefined) { - this.body('shows', name, ((content === null) ? undefined : content)); - } - - return ((content !== undefined) ? - this : - (this._body.shows) ? this._body.shows[name] : undefined - ); -}; - - -/** - * get, create, update or delete a view - * - * @param {string} name name of the view - * @param {string} map string representation of the map function; if you set - * this to null, the view will be deleted - * @param {?string} reduce string representation of the reduce function - * @return {cushion.Design|object} if you set a view, you will get this design - * document, otherwise you will get the view object with the string - * representations of the map and reduce functions - */ -Design.prototype.view = function(name, map, reduce) { - var view = {}; - - if (reduce) { - view.reduce = reduce; - } - - if (map !== undefined) { - view.map = map; - - this.body('views', name, ((map === null) ? undefined : view)); - } - - return ((map !== undefined) ? - this : - (this._body.views) ? this._body.views[name] : undefined - ); -}; - - -/** - * returns some infos about the design document and the views - * - * @param {function(error, info)} callback function that will be called, after - * getting the infos or if there was an error - */ -Design.prototype.viewInfo = function(callback) { - this._connection.request({ - 'method': 'GET', - 'path': this._database.name() + '/' + this._id + '/_info', - 'callback': callback - }); -}; - - -exports.Design = Design; - -}); - -require.define("/user.js",function(require,module,exports,__dirname,__filename,process){// jshint settings -/*global require: false, exports: false */ - -var crypto = require('crypto'); - -/** - * user object - * - * @constructor - * @param {string} name name of the user - * @param {cushion.Connection} connection cushion connection object - */ -var user = function(connection) { - this._connection = connection; -}; - - -/** - * adds a role - * - * @param {string} name name of the user - * @param {string|array} role a single role or a list of roles - * @param {function(error, added)} callback function that will be called after - * saving the role(s), or if there was an error - */ -user.prototype.addRole = function(name, role, callback) { - var roles = (typeof(role) === 'string') ? [role] : role; - - this._connection.database('_users').document( - 'org.couchdb.user:' + name - ).load(function(error, document) { - document.body( - 'roles', - document.body('roles').concat(roles) - ).save(function(error, document) { - callback(error, (error) ? null : true); - }); - }); -}; - - -/** - * creates a user - * - * @param {string} name name of the user - * @param {string} password password for the user - * @param {array|function(error, created)} rolesOrCallback list of roles - * for this user or function that will be called after creating the user - * account, or if there was an error - * @param {?function(error, created)} callback function that will be called - * after creating the user account, or if there was an error - */ -user.prototype.create = function( - name, - password, - rolesOrCallback, - callback -) { - var roles = (typeof(rolesOrCallback) === 'object') ? rolesOrCallback : [], - callback = callback || rolesOrCallback, - salt; - - // first we have to check the couchdb version - // because with couchdb <1.2.0 we have to create the salt and password hash - // - // yes we could always create the sha password and salt, but at couchdb 1.3.0 - // password generation will change and then we would need a third variant - this._lower120((function(error, lower) { - if (error) { - callback(error, null); - } else { - if (lower === true) { - salt = this._salt(); - password = this._hash(password, salt); - - this._connection.database('_users').document( - 'org.couchdb.user:' + name - ).body({ - 'name': name, - 'type': 'user', - 'roles': roles, - 'password_sha': password, - 'salt': salt - }).save(function(error, document) { - callback(error, (error) ? null : true); - }); - } else { - this._connection.database('_users').document( - 'org.couchdb.user:' + name - ).body({ - 'name': name, - 'type': 'user', - 'roles': roles, - 'password': password - }).save(function(error, document) { - callback(error, (error) ? null : true); - }); - } - } - }).bind(this)); -}; - - -/** - * deletes an user - * - * @param {string} name name of the user - * @param {function(error, deleted)} callback function that will be called, - * after deleting the user account, or if there was an error - */ -user.prototype.delete = function(name, callback) { - var document = this._connection.database('_users').document( - 'org.couchdb.user:' + name - ); - - document.info(function(error, info) { - if (error) { - callback(error, null); - } else { - document.destroy(function(error, document) { - callback(error, (error) ? null : true); - }); - } - }); -}; - - -/** - * deletes one or more roles from the user - * - * @param {string} name name of the user - * @param {string|array} role a single role or a list of roles - * @param {function(error, deleted)} callback function that will be called after - * deleting the role(s), or if there was an error - */ -user.prototype.deleteRole = function(name, role, callback) { - var deleteRoles = (typeof(role) === 'string') ? [role] : role; - - this._connection.database('_users').document( - 'org.couchdb.user:' + name - ).load(function(error, document) { - if (error) { - callback(error, null); - } else { - document.body( - 'roles', - document.body('roles').filter(function(role, index, roles) { - return deleteRoles.some(function(deleteRole, index, allDeleteRoles) { - return (deleteRole === role); - }); - }) - ).save(function(error, document) { - callback(error, (error) ? null : true); - }); - } - }); -}; - - -/** - * getting list of roles - * - * @param {string} name name of the user - * @param {function(error, roles)} callback function that will be called after - * getting the roles, or if there was an error - */ -user.prototype.getRoles = function(name, callback) { - this._connection.database('_users').document( - 'org.couchdb.user:' + name - ).load(function(error, document) { - callback(error, (error) ? null : document.body('roles')); - }); -}; - - -/** - * generate password hash - * - * @private - * @param {string} password plain password string - * @param {string} salt hexadecimal salt string - */ -user.prototype._hash = function(password, salt) { - return crypto.createHash('sha1').update(password + salt).digest('hex'); -}; - - -/** - * generate salt - * - * @private - * @return {string} hexadecimal random string - */ -user.prototype._salt = function() { - return crypto.randomBytes(16).toString('hex'); -}; - - -/** - * version lower than 1.2.0? - * - * @private - * @param {function(error, lower)} callback function that will be called after - * looking for lower version or if there was an error - */ -user.prototype._lower120 = function(callback) { - this._connection.version(function(error, version) { - if (error) { - callback(error, null); - } else { - version = version.split('.').map(function(part, index, complete) { - return parseInt(part, 10); - }); - - callback(null, (version[0] < 1 || (version[0] === 1 && version[1] < 2))); - } - }); -}; - - -/** - * sets/changes the password - * - * @param {string} name name of the user - * @param {password} password for the user - * @param {function(error, changed)} callback function that will be called after - * changing the password, or if there was an error - */ -user.prototype.password = function(name, password, callback) { - var salt; - - this._connection.database('_users').document('org.couchdb.user:' + name).load( - (function(error, document) { - if (error) { - callback(error, null); - } else { - this._lower120((function(error, lower) { - if (error) { - callback(error, null); - } else { - if (lower === true) { - salt = this._salt(); - password = this._hash(password, salt); - - document.body('password_sha', password).body('salt', salt); - } else { - document - .body('password_sha', undefined) - .body('salt', undefined) - .body('password', password); - } - - document.save(function(error, document) { - callback(error, (error) ? null : true); - }); - } - }).bind(this)); - } - }).bind(this) - ); -}; - - -exports.User = user; - -}); - -require.define("crypto",function(require,module,exports,__dirname,__filename,process){module.exports = require("crypto-browserify") -}); - -require.define("/node_modules/crypto-browserify/package.json",function(require,module,exports,__dirname,__filename,process){module.exports = {} -}); - -require.define("/node_modules/crypto-browserify/index.js",function(require,module,exports,__dirname,__filename,process){var sha = require('./sha') -var rng = require('./rng') - -var algorithms = { - sha1: { - hex: sha.hex_sha1, - binary: sha.b64_sha1, - ascii: sha.str_sha1 - } -} - -function error () { - var m = [].slice.call(arguments).join(' ') - throw new Error([ - m, - 'we accept pull requests', - 'http://github.com/dominictarr/crypto-browserify' - ].join('\n')) -} - -exports.createHash = function (alg) { - alg = alg || 'sha1' - if(!algorithms[alg]) - error('algorithm:', alg, 'is not yet supported') - var s = '' - var _alg = algorithms[alg] - return { - update: function (data) { - s += data - return this - }, - digest: function (enc) { - enc = enc || 'binary' - var fn - if(!(fn = _alg[enc])) - error('encoding:', enc , 'is not yet supported for algorithm', alg) - var r = fn(s) - s = null //not meant to use the hash after you've called digest. - return r - } - } -} - -exports.randomBytes = function(size, callback) { - if (callback && callback.call) { - try { - callback.call(this, undefined, rng(size)); - } catch (err) { callback(err); } - } else { - return rng(size); - } -} - -// the least I can do is make error messages for the rest of the node.js/crypto api. -;['createCredentials' -, 'createHmac' -, 'createCypher' -, 'createCypheriv' -, 'createDecipher' -, 'createDecipheriv' -, 'createSign' -, 'createVerify' -, 'createDeffieHellman' -, 'pbkdf2'].forEach(function (name) { - exports[name] = function () { - error('sorry,', name, 'is not implemented yet') - } -}) - -}); - -require.define("/node_modules/crypto-browserify/sha.js",function(require,module,exports,__dirname,__filename,process){/* - * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined - * in FIPS PUB 180-1 - * Version 2.1a Copyright Paul Johnston 2000 - 2002. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for details. - */ - -exports.hex_sha1 = hex_sha1; -exports.b64_sha1 = b64_sha1; -exports.str_sha1 = str_sha1; -exports.hex_hmac_sha1 = hex_hmac_sha1; -exports.b64_hmac_sha1 = b64_hmac_sha1; -exports.str_hmac_sha1 = str_hmac_sha1; - -/* - * Configurable variables. You may need to tweak these to be compatible with - * the server-side, but the defaults work in most cases. - */ -var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ -var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ -var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ - -/* - * These are the functions you'll usually want to call - * They take string arguments and return either hex or base-64 encoded strings - */ -function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));} -function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));} -function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));} -function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));} -function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));} -function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));} - -/* - * Perform a simple self-test to see if the VM is working - */ -function sha1_vm_test() -{ - return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d"; -} - -/* - * Calculate the SHA-1 of an array of big-endian words, and a bit length - */ -function core_sha1(x, len) -{ - /* append padding */ - x[len >> 5] |= 0x80 << (24 - len % 32); - x[((len + 64 >> 9) << 4) + 15] = len; - - var w = Array(80); - var a = 1732584193; - var b = -271733879; - var c = -1732584194; - var d = 271733878; - var e = -1009589776; - - for(var i = 0; i < x.length; i += 16) - { - var olda = a; - var oldb = b; - var oldc = c; - var oldd = d; - var olde = e; - - for(var j = 0; j < 80; j++) - { - if(j < 16) w[j] = x[i + j]; - else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); - var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), - safe_add(safe_add(e, w[j]), sha1_kt(j))); - e = d; - d = c; - c = rol(b, 30); - b = a; - a = t; - } - - a = safe_add(a, olda); - b = safe_add(b, oldb); - c = safe_add(c, oldc); - d = safe_add(d, oldd); - e = safe_add(e, olde); - } - return Array(a, b, c, d, e); - -} - -/* - * Perform the appropriate triplet combination function for the current - * iteration - */ -function sha1_ft(t, b, c, d) -{ - if(t < 20) return (b & c) | ((~b) & d); - if(t < 40) return b ^ c ^ d; - if(t < 60) return (b & c) | (b & d) | (c & d); - return b ^ c ^ d; -} - -/* - * Determine the appropriate additive constant for the current iteration - */ -function sha1_kt(t) -{ - return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : - (t < 60) ? -1894007588 : -899497514; -} - -/* - * Calculate the HMAC-SHA1 of a key and some data - */ -function core_hmac_sha1(key, data) -{ - var bkey = str2binb(key); - if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz); - - var ipad = Array(16), opad = Array(16); - for(var i = 0; i < 16; i++) - { - ipad[i] = bkey[i] ^ 0x36363636; - opad[i] = bkey[i] ^ 0x5C5C5C5C; - } - - var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz); - return core_sha1(opad.concat(hash), 512 + 160); -} - -/* - * Add integers, wrapping at 2^32. This uses 16-bit operations internally - * to work around bugs in some JS interpreters. - */ -function safe_add(x, y) -{ - var lsw = (x & 0xFFFF) + (y & 0xFFFF); - var msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return (msw << 16) | (lsw & 0xFFFF); -} - -/* - * Bitwise rotate a 32-bit number to the left. - */ -function rol(num, cnt) -{ - return (num << cnt) | (num >>> (32 - cnt)); -} - -/* - * Convert an 8-bit or 16-bit string to an array of big-endian words - * In 8-bit function, characters >255 have their hi-byte silently ignored. - */ -function str2binb(str) -{ - var bin = Array(); - var mask = (1 << chrsz) - 1; - for(var i = 0; i < str.length * chrsz; i += chrsz) - bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32); - return bin; -} - -/* - * Convert an array of big-endian words to a string - */ -function binb2str(bin) -{ - var str = ""; - var mask = (1 << chrsz) - 1; - for(var i = 0; i < bin.length * 32; i += chrsz) - str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask); - return str; -} - -/* - * Convert an array of big-endian words to a hex string. - */ -function binb2hex(binarray) -{ - var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; - var str = ""; - for(var i = 0; i < binarray.length * 4; i++) - { - str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + - hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); - } - return str; -} - -/* - * Convert an array of big-endian words to a base-64 string - */ -function binb2b64(binarray) -{ - var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - var str = ""; - for(var i = 0; i < binarray.length * 4; i += 3) - { - var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16) - | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) - | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF); - for(var j = 0; j < 4; j++) - { - if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; - else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); - } - } - return str; -} - - -}); - -require.define("/node_modules/crypto-browserify/rng.js",function(require,module,exports,__dirname,__filename,process){// Original code adapted from Robert Kieffer. -// details at https://github.com/broofa/node-uuid -(function() { - var _global = this; - - var mathRNG, whatwgRNG; - - // NOTE: Math.random() does not guarantee "cryptographic quality" - mathRNG = function(size) { - var bytes = new Array(size); - var r; - - for (var i = 0, r; i < size; i++) { - if ((i & 0x03) == 0) r = Math.random() * 0x100000000; - bytes[i] = r >>> ((i & 0x03) << 3) & 0xff; - } - - return bytes; - } - - // currently only available in webkit-based browsers. - if (_global.crypto && crypto.getRandomValues) { - var _rnds = new Uint32Array(4); - whatwgRNG = function(size) { - var bytes = new Array(size); - crypto.getRandomValues(_rnds); - - for (var c = 0 ; c < size; c++) { - bytes[c] = _rnds[c >> 2] >>> ((c & 0x03) * 8) & 0xff; - } - return bytes; - } - } - - module.exports = whatwgRNG || mathRNG; - -}()) -}); - -require.define("https",function(require,module,exports,__dirname,__filename,process){module.exports = require('http'); - -}); - -require.define("/cushion.js",function(require,module,exports,__dirname,__filename,process){// jshint settings -/*global require: false, exports: false */ - -var http = require('http'), - defaultOptions = require('./config.js'), - Database = require('./database.js').Database, - UserApi = require('./user.js').User; - -/** - * create connection to a couchdb - * - * @param {string} [host=this._options.host] host address - * @param {number} [port=this._options.port] port - * @param {string} [username=this._options.username] username for authorization - * @param {string} [password=this._options.password] password for authorization - * @param {object} additional additional options: - * {boolean} [secure=false] set this to true, if you want https-connections - * {string} [path=''] set an additional path, if you want to connect through - * this (e.g. a proxy, because of connecting from browser) - */ -var cushion = function(host, port, username, password, additional) { - additional = additional || {}; - - this._methodMatch = /^GET|PUT|POST|DELETE|HEAD|COPY$/i; - this._options = { - 'host': host || defaultOptions.host, - 'port': port || defaultOptions.port, - 'username': username || defaultOptions.username, - 'password': password || defaultOptions.password, - 'secure': additional.secure || defaultOptions.secure, - 'path': (additional.path) ? additional.path + '/' : defaultOptions.path - }; - - if (this._options.secure === true) { - http = require('https'); - } -}; - - -/** - * returns a list of active tasks - * - * @param {function(error, activeTasks)} callback function that will called, - * after getting the list of active tasks or if there was an error - */ -cushion.prototype.activeTasks = function(callback) { - this.request({ - 'method': 'GET', - 'path': '_active_tasks', - 'callback': callback - }); -}; - - -/** - * set or get configuration params - * if you set: - * one param: you will get the complete configuration - * two params: you will get all options of the specific section - * three params: you will get the content of the specific option - * four params: you set a specific option to the new value, or you delete the - * given option, if you set value to null - * - * @param {string|function(error, configuration)} sectionOrCallback a section of - * different config params or function that will be called, after getting - * the whole configuration or if there was an error - * @param {?string|function(error, options)} optionOrCallback an specific option - * or a function, that will be called, after getting the options of the - * section of if there was an error - * @param {?string|function(error, value)} valueOrCallback the new value for the - * option or function that will be called, after getting the content of the - * option; if you set the value to null, option will be deleted - * @param {?function(error, saved)} callback function that will be called after - * saving the new value, or if there was an error - */ -cushion.prototype.config = function( - sectionOrCallback, - optionOrCallback, - valueOrCallback, - callback -) { - var section = (typeof(sectionOrCallback) === 'string') ? - sectionOrCallback : - null, - option = (typeof(optionOrCallback) === 'string') ? - optionOrCallback : - null, - value = ( - typeof(valueOrCallback) === 'string' || - typeof(valueOrCallback) === 'number' || - valueOrCallback === null - ) ? valueOrCallback : undefined, - options; - callback = callback || - valueOrCallback || - optionOrCallback || - sectionOrCallback; - - options = { - 'method': (value !== undefined) ? - ((value === null) ? 'DELETE' : 'PUT') : - 'GET', - 'path': '_config' + - ((section) ? '/' + section : '') + - ((option) ? '/' + option : ''), - 'callback': function(error, response) { - if (error) { - response = null; - } else { - response = (value !== undefined) ? true : response; - } - - callback(error, response); - } - }; - - // do we set a new value? - if (typeof(value) === 'string' || typeof(value) === 'number') { - options.body = '"' + value + '"'; - } - - this.request(options); -}; - - -/** - * creates an admin - * - * @param {string} name name of the admin account - * @param {string} password password of the admin account - * @param {function(error, created)} callback function that will be called after - * creating the admin account, or if there was an error - */ -cushion.prototype.createAdmin = function(name, password, callback) { - // first we have to create a new option at the config - this.config('admins', name, password, (function(error, created) { - // after that we have to create a user document - var database, - document; - - if (created === true) { - database = this.database('_users'); - document = database.document('org.couchdb.user:' + name); - document.body('name', name); - document.body('type', 'user'); - document.body('roles', []); - document.save(function(error, document) { - if (error) { - callback(error, null); - } else { - callback(error, true); - } - }); - } else { - callback(error, null); - } - }).bind(this)); -}; - - -/** - * gives a connection to a specific database - * - * @param {string} name name of the database - * @return {Object} the database object - */ -cushion.prototype.database = function(name) { - return new Database(name, this); -}; - - -/** - * deletes an admin - * - * @param {string} name username of the admin - * @param {function(error, deleted)} callback function that will be called, - * after deleting the admin account, or if there was an error - */ -cushion.prototype.deleteAdmin = function(name, callback) { - // first we have to delete the admin option - this.config('admins', name, null, (function(error, deleted) { - // after that we have to delete the user document - var database, - document; - - if (deleted === true) { - database = this.database('_users'); - document = database.document('org.couchdb.user:' + name); - document.load(function(error, document) { - if (document) { - document.destroy(function(error, document) { - if (document) { - callback(null, true); - } else { - callback(error, null); - } - }); - } else { - callback(error, null); - } - }); - } else { - callback(error, null); - } - }).bind(this)); -}; - - -/** - * retrieving a list of databases - * - * - * @param {boolean|function(error, databases)} noCouchRelatedOrCallback filters - * all couch related databases, so the list has only databases which a user - * has set up or function that will be called after retrieving a list of - * databases, or if there was an error - * @param {?function()} callback function that will be called after retrieving a - * list of databases, or if there was an error - */ - -cushion.prototype.listDatabases = function(noCouchRelatedOrCallback, callback) { - var noCouchRelated = (callback) ? noCouchRelatedOrCallback : null; - callback = callback || noCouchRelatedOrCallback; - - this.request({ - 'method': 'GET', - 'path': '_all_dbs', - 'callback': (function (error, response) { - if (error === null && response !== null) { - // filter couch related databases, if user want's so - if (noCouchRelated === true) { - response = response.filter(function(dbName, index, list) { - return (dbName[0] !== '_'); - }); - } - - // create database objects - response = response.map(function(dbName) { - return this.database(dbName); - }, this); - } - - callback(error, response); - }).bind(this) - }); -}; - - -/** - * returns the tail of the server's log file - * - * @param {number|function(error, log)} bytesOrCallback number of bytes how many - * do you want from the tail or function that will be called, after getting - * the log or if there was an error - * @param {?function(error, log)} callback function that will be called, after - * getting the log or if there was an error - */ -cushion.prototype.log = function(bytesOrCallback, callback) { - var bytes = (arguments.length > 1) ? bytesOrCallback : null; - callback = callback || bytesOrCallback; - - this.request({ - 'method': 'GET', - 'path': '_log' + ((bytes) ? '?bytes=' + bytes : ''), - 'callback': callback - }); -}; - - -/** - * wrapper function for any request to the couchdb - * - * @param {Function} callback function that will be called after all data events - * @param {http.ClientResponse} response the http response object - */ -cushion.prototype._request = function(callback, response) { - var content = ''; - - response.on('data', function(chunk) { - content += chunk; - }); - - response.on('end', (function() { - try { - if ( - response.headers['content-type'] === 'application/json' && - content.length > 0 - ) { - content = JSON.parse(content); - } - - if (response.statusCode === 404 && content.length === 0) { - content = { - 'error': 'not_found', - 'reason': 'missing' - }; - } - - callback( - (content.error) ? content : null, - (!content.error) ? content : null, - response.headers || null - ); - } catch(error) { - callback(error, null, null); - } - }).bind(this)); -}; - - -/** - * sends a request to the couch - * - * @param {object} properties options for the request - * method: {string} http method, can be GET, PUT, POST, DELETE, HEAD, COPY - * path: {string} uri path after domain - * headers: {Object} key/value-pairs of additional http headers - * body: {Object|Array} additional body - * callback: {function(error, response)} function that will be called, - * after getting the response or if there was an error - */ -cushion.prototype.request = function(properties) { - var options = { - 'host': this._options.host, - 'port': this._options.port, - 'method': ( - typeof(properties.method) === 'string' && - properties.method.match(this._methodMatch) !== null - ) ? - properties.method : - 'GET', - 'path': '/' + this._options.path + (properties.path || ''), - 'auth': this._options.username + ':' + this._options.password, - 'headers': properties.headers || {} - }, - request; - - // make sure, that we get application/json response from couchdb - options.headers.Accept = options.headers.Accept || '*/*,application/json'; - options.headers['Content-Type'] = options.headers['Content-Type'] || - 'application/json'; - - // set up request object - request = http.request( - options, - this._request.bind(this, properties.callback) - ); - - // define callback, if there is an error - request.on('error', (function(error) { - properties.callback(error, null, null); - }).bind(this)); - - // adding optional body to the request - if (properties.body) { - if (typeof(properties.body) === 'object') { - request.write(JSON.stringify(properties.body)); - } else { - request.write(properties.body); - } - } - - // starting request - request.end(); -}; - - -/** - * restarts the couchdb - * - * @param {function(error, restart)} callback function that will be called, - * after initializing the restart or if there was an error - */ -cushion.prototype.restart = function(callback) { - this.request({ - 'method': 'POST', - 'path': '_restart', - 'callback': function(error, restart) { - if (error && error.code === 'ECONNRESET') { - error = null; - restart = true; - } - - callback(error, restart); - } - }); -}; - - -/** - * returns server statistics - * - * @param {function(error, stats)} callback function that will be called, after - * getting the statistics of if there was an error - */ -cushion.prototype.stats = function(callback) { - this.request({ - 'method': 'GET', - 'path': '_stats', - 'callback': callback - }); -}; - - -/** - * get the user object - * - * @return {cushion.User} the user object - */ -cushion.prototype.user = function() { - return new UserApi(this); -}; - - -/** - * returns a list of generated uuids - * - * @param {number|function(error, uuidList)} countOrCallback number of uuids to - * generate or function that will be called, after getting the list of uuids - * or if there was an error - * @param {?function(error, uuidList)} callback function that will be called, - * after getting the list of uuids or if there was an error - */ -cushion.prototype.uuids = function(countOrCallback, callback) { - var count = (arguments.length > 1) ? countOrCallback : null; - callback = callback || countOrCallback; - - this.request({ - 'method': 'GET', - 'path': '_uuids' + ((count) ? '?count=' + count : ''), - 'callback': function(error, uuidList) { - if (uuidList) { - uuidList = uuidList.uuids; - } - - callback(error, uuidList); - } - }); -}; - - -/** - * gets the version of the couchdb - * - * @param {Function(version)} callback function that will be called after - */ -cushion.prototype.version = function(callback) { - this.request({ - 'method': 'GET', - 'path': '', - 'callback': function(error, response) { - if (response !== null) { - response = response.version; - } - - callback(error, response); - } - }); -}; - - -exports.Connection = cushion; - -}); -require("/cushion.js"); -})(); diff --git a/cushion.browser.min.js b/cushion.browser.min.js deleted file mode 100644 index 8161c6c..0000000 --- a/cushion.browser.min.js +++ /dev/null @@ -1,2 +0,0 @@ -(function(){var a=function(b,c){var d=a.resolve(b,c||"/"),e=a.modules[d];if(!e)throw new Error("Failed to resolve module "+b+", tried "+d);var f=a.cache[d],g=f?f.exports:e();return g};a.paths=[],a.modules={},a.cache={},a.extensions=[".js",".coffee",".json"],a._core={assert:!0,events:!0,fs:!0,path:!0,vm:!0},a.resolve=function(){return function(b,c){function h(b){b=d.normalize(b);if(a.modules[b])return b;for(var c=0;c=0;e--){if(b[e]==="node_modules")continue;var f=b.slice(0,e+1).join("/")+"/node_modules";c.push(f)}return c}c||(c="/");if(a._core[b])return b;var d=a.modules.path();c=d.resolve("/",c);var e=c||"/";if(b.match(/^(?:\.\.?\/|\/)/)){var f=h(d.resolve(e,b))||i(d.resolve(e,b));if(f)return f}var g=j(b,e);if(g)return g;throw new Error("Cannot find module '"+b+"'")}}(),a.alias=function(b,c){var d=a.modules.path(),e=null;try{e=a.resolve(b+"/package.json","/")}catch(f){e=a.resolve(b,"/")}var g=d.dirname(e),h=(Object.keys||function(a){var b=[];for(var c in a)b.push(c);return b})(a.modules);for(var i=0;i=0;d--){var e=a[d];e=="."?a.splice(d,1):e===".."?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c--;c)a.unshift("..");return a}var i=/^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;c.resolve=function(){var a="",b=!1;for(var c=arguments.length;c>=-1&&!b;c--){var d=c>=0?arguments[c]:f.cwd();if(typeof d!="string"||!d)continue;a=d+"/"+a,b=d.charAt(0)==="/"}return a=h(g(a.split("/"),function(a){return!!a}),!b).join("/"),(b?"/":"")+a||"."},c.normalize=function(a){var b=a.charAt(0)==="/",c=a.slice(-1)==="/";return a=h(g(a.split("/"),function(a){return!!a}),!b).join("/"),!a&&!b&&(a="."),a&&c&&(a+="/"),(b?"/":"")+a},c.join=function(){var a=Array.prototype.slice.call(arguments,0);return c.normalize(g(a,function(a,b){return a&&typeof a=="string"}).join("/"))},c.dirname=function(a){var b=i.exec(a)[1]||"",c=!1;return b?b.length===1||c&&b.length<=3&&b.charAt(1)===":"?b:b.substring(0,b.length-1):"."},c.basename=function(a,b){var c=i.exec(a)[2]||"";return b&&c.substr(-1*b.length)===b&&(c=c.substr(0,c.length-b.length)),c},c.extname=function(a){return i.exec(a)[3]||""}}),a.define("__browserify_process",function(a,b,c,d,e,f){var f=b.exports={};f.nextTick=function(){var a=typeof window!="undefined"&&window.setImmediate,b=typeof window!="undefined"&&window.postMessage&&window.addEventListener;if(a)return window.setImmediate;if(b){var c=[];return window.addEventListener("message",function(a){if(a.source===window&&a.data==="browserify-tick"){a.stopPropagation();if(c.length>0){var b=c.shift();b()}}},!0),function(a){c.push(a),window.postMessage("browserify-tick","*")}}return function(a){setTimeout(a,0)}}(),f.title="browser",f.browser=!0,f.env={},f.argv=[],f.binding=function(b){if(b==="evals")return a("vm");throw new Error("No such module. (Possibly not yet loaded)")},function(){var b="/",c;f.cwd=function(){return b},f.chdir=function(d){c||(c=a("path")),b=c.resolve(d,b)}}()}),a.define("/package.json",function(a,b,c,d,e,f){b.exports={main:"./cushion"}}),a.define("/cushion.js",function(a,b,c,d,e,f){var g=a("http"),h=a("./config.js"),i=a("./database.js").Database,j=a("./user.js").User,k=function(b,c,d,e,f){f=f||{},this._methodMatch=/^GET|PUT|POST|DELETE|HEAD|COPY$/i,this._options={host:b||h.host,port:c||h.port,username:d||h.username,password:e||h.password,secure:f.secure||h.secure,path:f.path?f.path+"/":h.path},this._options.secure===!0&&(g=a("https"))};k.prototype.activeTasks=function(a){this.request({method:"GET",path:"_active_tasks",callback:a})},k.prototype.config=function(a,b,c,d){var e=typeof a=="string"?a:null,f=typeof b=="string"?b:null,g=typeof c=="string"||typeof c=="number"||c===null?c:undefined,h;d=d||c||b||a,h={method:g!==undefined?g===null?"DELETE":"PUT":"GET",path:"_config"+(e?"/"+e:"")+(f?"/"+f:""),callback:function(a,b){a?b=null:b=g!==undefined?!0:b,d(a,b)}};if(typeof g=="string"||typeof g=="number")h.body='"'+g+'"';this.request(h)},k.prototype.createAdmin=function(a,b,c){this.config("admins",a,b,function(b,d){var e,f;d===!0?(e=this.database("_users"),f=e.document("org.couchdb.user:"+a),f.body("name",a),f.body("type","user"),f.body("roles",[]),f.save(function(a,b){a?c(a,null):c(a,!0)})):c(b,null)}.bind(this))},k.prototype.database=function(a){return new i(a,this)},k.prototype.deleteAdmin=function(a,b){this.config("admins",a,null,function(c,d){var e,f;d===!0?(e=this.database("_users"),f=e.document("org.couchdb.user:"+a),f.load(function(a,c){c?c.destroy(function(a,c){c?b(null,!0):b(a,null)}):b(a,null)})):b(c,null)}.bind(this))},k.prototype.listDatabases=function(a,b){var c=b?a:null;b=b||a,this.request({method:"GET",path:"_all_dbs",callback:function(a,d){a===null&&d!==null&&(c===!0&&(d=d.filter(function(a,b,c){return a[0]!=="_"})),d=d.map(function(a){return this.database(a)},this)),b(a,d)}.bind(this)})},k.prototype.log=function(a,b){var c=arguments.length>1?a:null;b=b||a,this.request({method:"GET",path:"_log"+(c?"?bytes="+c:""),callback:b})},k.prototype._request=function(a,b){var c="";b.on("data",function(a){c+=a}),b.on("end",function(){try{b.headers["content-type"]==="application/json"&&c.length>0&&(c=JSON.parse(c)),b.statusCode===404&&c.length===0&&(c={error:"not_found",reason:"missing"}),a(c.error?c:null,c.error?null:c,b.headers||null)}catch(d){a(d,null,null)}}.bind(this))},k.prototype.request=function(a){var b={host:this._options.host,port:this._options.port,method:typeof a.method=="string"&&a.method.match(this._methodMatch)!==null?a.method:"GET",path:"/"+this._options.path+(a.path||""),auth:this._options.username+":"+this._options.password,headers:a.headers||{}},c;b.headers.Accept=b.headers.Accept||"*/*,application/json",b.headers["Content-Type"]=b.headers["Content-Type"]||"application/json",c=g.request(b,this._request.bind(this,a.callback)),c.on("error",function(b){a.callback(b,null,null)}.bind(this)),a.body&&(typeof a.body=="object"?c.write(JSON.stringify(a.body)):c.write(a.body)),c.end()},k.prototype.restart=function(a){this.request({method:"POST",path:"_restart",callback:function(b,c){b&&b.code==="ECONNRESET"&&(b=null,c=!0),a(b,c)}})},k.prototype.stats=function(a){this.request({method:"GET",path:"_stats",callback:a})},k.prototype.user=function(){return new j(this)},k.prototype.uuids=function(a,b){var c=arguments.length>1?a:null;b=b||a,this.request({method:"GET",path:"_uuids"+(c?"?count="+c:""),callback:function(a,c){c&&(c=c.uuids),b(a,c)}})},k.prototype.version=function(a){this.request({method:"GET",path:"",callback:function(b,c){c!==null&&(c=c.version),a(b,c)}})},c.Connection=k}),a.define("http",function(a,b,c,d,e,f){b.exports=a("http-browserify")}),a.define("/node_modules/http-browserify/package.json",function(a,b,c,d,e,f){b.exports={main:"index.js",browserify:"index.js"}}),a.define("/node_modules/http-browserify/index.js",function(a,b,c,d,e,f){var g=b.exports,h=a("events").EventEmitter,i=a("./lib/request");g.request=function(a,b){a||(a={}),a.host||(a.host=window.location.host.split(":")[0]),a.port||(a.port=window.location.port);var c=new i(new j,a);return b&&c.on("response",b),c},g.get=function(a,b){a.method="GET";var c=g.request(a,b);return c.end(),c},g.Agent=function(){},g.Agent.defaultMaxSockets=4;var j=function(){if(typeof window=="undefined")throw new Error("no window object present");if(window.XMLHttpRequest)return window.XMLHttpRequest;if(window.ActiveXObject){var a=["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.3.0","Microsoft.XMLHTTP"];for(var b=0;b0&&this._events[a].length>c&&(this._events[a].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[a].length),console.trace())}this._events[a].push(b)}else this._events[a]=[this._events[a],b];return this},g.prototype.on=g.prototype.addListener,g.prototype.once=function(a,b){var c=this;return c.on(a,function d(){c.removeListener(a,d),b.apply(this,arguments)}),this},g.prototype.removeListener=function(a,b){if("function"!=typeof b)throw new Error("removeListener only takes instances of Function");if(!this._events||!this._events[a])return this;var c=this._events[a];if(h(c)){var d=c.indexOf(b);if(d<0)return this;c.splice(d,1),c.length==0&&delete this._events[a]}else this._events[a]===b&&delete this._events[a];return this},g.prototype.removeAllListeners=function(a){return a&&this._events&&this._events[a]&&(this._events[a]=null),this},g.prototype.listeners=function(a){return this._events||(this._events={}),this._events[a]||(this._events[a]=[]),h(this._events[a])||(this._events[a]=[this._events[a]]),this._events[a]}}),a.define("/node_modules/http-browserify/lib/request.js",function(a,b,c,d,e,f){var g=a("events").EventEmitter,h=a("./response"),i=a("concat-stream"),j=b.exports=function(a,b){var c=this;c.xhr=a,c.body=i();var d=b.host+":"+b.port+(b.path||"/");a.open(b.method||"GET",(b.scheme||"http")+"://"+d,!0),b.headers&&Object.keys(b.headers).forEach(function(d){if(!c.isSafeRequestHeader(d))return;var e=b.headers[d];Array.isArray(e)?e.forEach(function(b){a.setRequestHeader(d,b)}):a.setRequestHeader(d,e)});var e=new h;e.on("ready",function(){c.emit("response",e)}),a.onreadystatechange=function(){e.handle(a)}};j.prototype=new g,j.prototype.setHeader=function(a,b){if(Array.isArray&&Array.isArray(b)||b instanceof Array)for(var c=0;cthis.offset&&(this.emit("data",b.slice(this.offset)),this.offset=b.length)}}),a.define("/node_modules/http-browserify/node_modules/concat-stream/package.json",function(a,b,c,d,e,f){b.exports={}}),a.define("/node_modules/http-browserify/node_modules/concat-stream/index.js",function(a,b,c,d,e,f){function i(a){g.Stream.call(this),this.writable=!0,a&&(this.cb=a),this.body=[],this.cb&&this.on("error",a)}var g=a("stream"),h=a("util");h.inherits(i,g.Stream),i.prototype.write=function(a){this.body.push(a)},i.prototype.arrayConcat=function(a){return a.length===0?[]:a.length===1?a[0]:a.reduce(function(a,b){return a.concat(b)})},i.prototype.isArray=function(a){var b=Array.isArray(a),c=a.toString().match(/Array/);return b||c},i.prototype.getBody=function(){if(this.body.length===0)return;return typeof this.body[0]=="string"?this.body.join(""):this.isArray(this.body[0])?this.arrayConcat(this.body):typeof Buffer!="undefined"&&Buffer.isBuffer(this.body[0])?Buffer.concat(this.body):this.body},i.prototype.end=function(){this.cb&&this.cb(!1,this.getBody())},b.exports=function(a){return new i(a)},b.exports.ConcatStream=i}),a.define("stream",function(a,b,c,d,e,f){function i(){g.EventEmitter.call(this)}var g=a("events"),h=a("util");h.inherits(i,g.EventEmitter),b.exports=i,i.Stream=i,i.prototype.pipe=function(a,b){function d(b){a.writable&&!1===a.write(b)&&c.pause&&c.pause()}function e(){c.readable&&c.resume&&c.resume()}function g(){if(f)return;f=!0,a._pipeCount--,j();if(a._pipeCount>0)return;a.end()}function h(){if(f)return;f=!0,a._pipeCount--,j();if(a._pipeCount>0)return;a.destroy()}function i(a){j();if(this.listeners("error").length===0)throw a}function j(){c.removeListener("data",d),a.removeListener("drain",e),c.removeListener("end",g),c.removeListener("close",h),c.removeListener("error",i),a.removeListener("error",i),c.removeListener("end",j),c.removeListener("close",j),a.removeListener("end",j),a.removeListener("close",j)}var c=this;c.on("data",d),a.on("drain",e),!a._isStdio&&(!b||b.end!==!1)&&(a._pipeCount=a._pipeCount||0,a._pipeCount++,c.on("end",g),c.on("close",h));var f=!1;return c.on("error",i),a.on("error",i),c.on("end",j),c.on("close",j),a.on("end",j),a.on("close",j),a.emit("pipe",c),a}}),a.define("util",function(a,b,c,d,e,f){function h(a){return a instanceof Array||Array.isArray(a)||a&&a!==Object.prototype&&h(a.__proto__)}function i(a){return a instanceof RegExp||typeof a=="object"&&Object.prototype.toString.call(a)==="[object RegExp]"}function j(a){if(a instanceof Date)return!0;if(typeof a!="object")return!1;var b=Date.prototype&&o(Date.prototype),c=a.__proto__&&o(a.__proto__);return JSON.stringify(c)===JSON.stringify(b)}function k(a){return a<10?"0"+a.toString(10):a.toString(10)}function m(){var a=new Date,b=[k(a.getHours()),k(a.getMinutes()),k(a.getSeconds())].join(":");return[a.getDate(),l[a.getMonth()],b].join(" ")}var g=a("events");c.print=function(){},c.puts=function(){},c.debug=function(){},c.inspect=function(a,b,d,e){function k(a,d){if(a&&typeof a.inspect=="function"&&a!==c&&(!a.constructor||a.constructor.prototype!==a))return a.inspect(d);switch(typeof a){case"undefined":return g("undefined","undefined");case"string":var e="'"+JSON.stringify(a).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return g(e,"string");case"number":return g(""+a,"number");case"boolean":return g(""+a,"boolean")}if(a===null)return g("null","null");var l=n(a),m=b?o(a):l;if(typeof a=="function"&&m.length===0){if(i(a))return g(""+a,"regexp");var p=a.name?": "+a.name:"";return g("[Function"+p+"]","special")}if(j(a)&&m.length===0)return g(a.toUTCString(),"date");var q,r,s;h(a)?(r="Array",s=["[","]"]):(r="Object",s=["{","}"]);if(typeof a=="function"){var t=a.name?": "+a.name:"";q=i(a)?" "+a:" [Function"+t+"]"}else q="";j(a)&&(q=" "+a.toUTCString());if(m.length===0)return s[0]+q+s[1];if(d<0)return i(a)?g(""+a,"regexp"):g("[Object]","special");f.push(a);var u=m.map(function(b){var c,e;a.__lookupGetter__&&(a.__lookupGetter__(b)?a.__lookupSetter__(b)?e=g("[Getter/Setter]","special"):e=g("[Getter]","special"):a.__lookupSetter__(b)&&(e=g("[Setter]","special"))),l.indexOf(b)<0&&(c="["+b+"]"),e||(f.indexOf(a[b])<0?(d===null?e=k(a[b]):e=k(a[b],d-1),e.indexOf("\n")>-1&&(h(a)?e=e.split("\n").map(function(a){return" "+a}).join("\n").substr(2):e="\n"+e.split("\n").map(function(a){return" "+a}).join("\n"))):e=g("[Circular]","special"));if(typeof c=="undefined"){if(r==="Array"&&b.match(/^\d+$/))return e;c=JSON.stringify(""+b),c.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(c=c.substr(1,c.length-2),c=g(c,"name")):(c=c.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),c=g(c,"string"))}return c+": "+e});f.pop();var v=0,w=u.reduce(function(a,b){return v++,b.indexOf("\n")>=0&&v++,a+b.length+1},0);return w>50?u=s[0]+(q===""?"":q+"\n ")+" "+u.join(",\n ")+" "+s[1]:u=s[0]+q+" "+u.join(", ")+" "+s[1],u}var f=[],g=function(a,b){var c={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},d={special:"cyan",number:"blue","boolean":"yellow","undefined":"grey","null":"bold",string:"green",date:"magenta",regexp:"red"}[b];return d?"["+c[d][0]+"m"+a+"["+c[d][1]+"m":a};return e||(g=function(a,b){return a}),k(a,typeof d=="undefined"?2:d)};var l=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];c.log=function(a){},c.pump=null;var n=Object.keys||function(a){var b=[];for(var c in a)b.push(c);return b},o=Object.getOwnPropertyNames||function(a){var b=[];for(var c in a)Object.hasOwnProperty.call(a,c)&&b.push(c);return b},p=Object.create||function(a,b){var c;if(a===null)c={__proto__:null};else{if(typeof a!="object")throw new TypeError("typeof prototype["+typeof a+"] != 'object'");var d=function(){};d.prototype=a,c=new d,c.__proto__=a}return typeof b!="undefined"&&Object.defineProperties&&Object.defineProperties(c,b),c};c.inherits=function(a,b){a.super_=b,a.prototype=p(b.prototype,{constructor:{value:a,enumerable:!1,writable:!0,configurable:!0}})}}),a.define("/config.js",function(a,b,c,d,e,f){c.host="127.0.0.1",c.port=5984,c.username="",c.password="",c.secure=!1,c.path=""}),a.define("/database.js",function(a,b,c,d,e,f){var g=a("querystring"),h=a("./document.js").Document,i=a("./design.js").Design,j=function(a,b){this._name=a,this._connection=b};j.prototype.allDocuments=function(a,b){var c=typeof a=="object"?"?"+g.stringify(a,"&","="):"";b=b||a,this._connection.request({method:"GET",path:this.name()+"/_all_docs"+c,callback:function(a,c){var d,e={},f;if(a===null){d={total:c.total_rows,offset:c.offset};for(f=0;c.rows[f];++f)e[c.rows[f].id]=c.rows[f].value.rev}b(a,d,e)}.bind(this)})},j.prototype.cleanup=function(a){this._connection.request({method:"POST",path:this.name()+"/_view_cleanup",callback:function(b,c){a(b,c?!0:null)}})},j.prototype.compact=function(a,b){var c=b?a:undefined;b=b||a,this._connection.request({method:"POST",path:this.name()+"/_compact"+(c?"/"+c:""),callback:function(a,c){b(a,c?!0:null)}.bind(this)})},j.prototype.create=function(a){this._connection.request({method:"PUT",path:this.name(),callback:function(b,c){b===null&&c.ok===!0&&(c=!0),a(b,c)}.bind(this)})},j.prototype.destroy=function(a){this._connection.request({method:"DELETE",path:this.name(),callback:function(b,c){c&&c.ok===!0&&(c=!0),a(b,c)}})},j.prototype.document=function(a,b){var c=a&&a.match(/^_design\//)?i:h;return new c(a||null,b||null,this._connection,this)},j.prototype.exists=function(a){this._connection.request({method:"GET",path:this._name,callback:function(b,c){var d=!0;b&&b.error==="not_found"&&(b=null,d=!1),a(b,b===null?d:null)}})},j.prototype.info=function(a){this._connection.request({method:"GET",path:this._name,callback:a})},j.prototype.list=function(a,b,c,d,e,f){var h=typeof d=="object"?"?"+g.stringify(d,"&","="):typeof e=="object"?"?"+g.stringify(e,"&","="):"",i=typeof d=="string"?d:c,j=typeof d=="string"?"/"+c:"",k=this.name()+"/_design/"+a+"/_list/"+b+j+"/"+i+h;f=f||e||d,this._connection.request({method:"GET",path:k,callback:f})},j.prototype.name=function(){return this._name},j.prototype.revisionLimit=function(a,b){var c=b?a:null,d={method:c!==null?"PUT":"GET",path:this._name+"/_revs_limit"};b=b||a,c!==null&&(d.body=""+c),d.callback=function(a,d){a?b(a,null):c===null?b(null,d):b(null,!0)},this._connection.request(d)},j.prototype.show=function(a,b,c,d,e){var f=typeof c=="string"?"/"+c:"",h="";e=e||d||c,typeof c=="object"?h="?"+g.stringify(c,"&","="):typeof d=="object"&&(h="?"+g.stringify(d,"&","=")),this._connection.request({method:"GET",path:this._name+"/_design/"+a+"/_show/"+b+f+h,callback:e})},j.prototype.temporaryView=function(a,b,c,d){var e=typeof b=="string"?b:null,f=typeof b=="object"?b:c,h={map:a};d=d||c||b,f=g.stringify(f,"&","="),e!==null&&(h.reduce=e),this._connection.request({method:"POST",path:this.name()+"/_temp_view"+(f?"?"+f:""),body:h,callback:function(a,b){var c=null,e=null;a===null&&(c={total:b.total_rows,offset:b.offset},e=b.rows),d(a,c,e)}})},j.prototype.view=function(a,b,c,d){var e=typeof c=="object"?"?"+g.stringify(c,"&","="):"",f=this.name()+"/_design/"+a+"/_view/"+b;d=d||c,this._connection.request({method:"GET",path:f+e,callback:function(a,b){var c=null,e=null;a===null&&(c={total:b.total_rows,offset:b.offset},e=b.rows),d(a,c,e)}.bind(this)})},c.Database=j}),a.define("querystring",function(a,b,c,d,e,f){function l(a,b){if(!b)throw new TypeError("stringify expects an object");return b+"="+encodeURIComponent(a)}function m(a,b){var c=[];if(!b)throw new TypeError("stringify expects an object");for(var d=0;d0&&arguments.length>1?(a.forEach(function(a,d,e){d===e.length-1&&typeof b=="undefined"?delete c[a]:(c[a]=d===e.length-1?b:c[a]||{},c=c[a])}),d=this):a&&arguments.length>0?typeof b=="object"?(this._body=JSON.parse(JSON.stringify(b)),d=this):d=typeof this._body[b]=="object"?JSON.parse(JSON.stringify(this._body[b])):this._body[b]:d=JSON.parse(JSON.stringify(this._body)),d},h.prototype.copy=function(a,b,c){var d=c?"?rev="+b:"";c=c||b,this._id===null?f.nextTick(c({error:"no_copy",reason:this._error.noId},null,null)):this._connection.request({method:"COPY",headers:{Destination:a+d},path:this._database.name()+"/"+this._id+(this._revision?"?rev="+this._revision:""),callback:function(a,b){b&&(b=this._database.document(b.id,b.rev)),c(a,this,b)}.bind(this)})},h.prototype.deleteAttachment=function(a,b){this._connection.request({method:"DELETE",path:this._database.name()+"/"+this._id+"/"+a+"?rev="+this._revision,callback:function(a,c){a?c=!1:(this._revision=c.rev,c=!0),b(a,c)}.bind(this)})},h.prototype.destroy=function(a){this._id===null?f.nextTick(a({error:"no_delete",reason:this._error.noId},null)):this._revision===null?f.nextTick(a({error:"no_delete",reason:this._error.noRevision},null)):this._connection.request({method:"DELETE",path:this._database.name()+"/"+this._id+"?rev="+this._revision,callback:function(b,c){c&&(this._revision=c.rev),a(b,this)}.bind(this)})},h.prototype.getAttachment=function(a,b){this._connection.request({method:"GET",path:this._database.name()+"/"+this._id+"/"+a+"?rev="+this._revision,callback:b})},h.prototype.id=function(){return this._id},h.prototype.info=function(a){this._id===null?f.nextTick(a({error:"no_info",reason:"no document id was set"},null)):this._connection.request({method:"HEAD",path:this._database.name()+"/"+this._id,callback:function(b,c,d){var e=null;b===null&&(this._revision=d.etag.substr(1,d.etag.length-2),e={revision:this._revision,size:d["content-length"]}),a(b,e)}.bind(this)})},h.prototype.load=function(a){this._id===null?f.nextTick(a({error:"no_load",reason:this._error.noId},null)):this._connection.request({method:"GET",path:this._database.name()+"/"+this._id+(this._revision!==null?"?rev="+this._revision:""),callback:function(b,c){b===null&&this._saveContent(c),a(b,this)}.bind(this)})},h.prototype.revision=function(){return this._revision},h.prototype.save=function(a){var b=JSON.parse(JSON.stringify(this._body));this._revision!==null&&(b._rev=this._revision),this._connection.request({method:this._id===null?"POST":"PUT",path:this._database.name()+(this._id===null?"":"/"+this._id),body:b,callback:function(b,c){b===null&&(this._id=c.id,this._revision=c.rev),a(b,this)}.bind(this)})},h.prototype.saveAttachment=function(a,b,c,d){var e=typeof c=="string"?c:a.split("/").pop();d=d||c,g.readFile(a,"utf8",function(c,g){c?f.nextTick(d({error:"no_file",reason:this._error.noFile+": "+a},null)):this._connection.request({method:"PUT",path:this._database.name()+"/"+this._id+"/"+e+"?rev="+this._revision,headers:{"Content-Length":g.length,"Content-Type":b},body:g,callback:function(a,b){a?b=!1:(this._revision=b.rev,b=!0),d(a,b)}.bind(this)})}.bind(this))},h.prototype._saveContent=function(a){var b;a=JSON.parse(JSON.stringify(a)),this._body={};for(b in a)b[0]==="_"?b==="_rev"&&(this._revision=a[b]):this._body[b]=a[b]},c.Document=h}),a.define("fs",function(a,b,c,d,e,f){}),a.define("/design.js",function(a,b,c,d,e,f){var g=a("util"),h=a("./document.js").Document,i=function(a,b,c,d){h.call(this,a,b,c,d)};g.inherits(i,h),i.prototype.compact=function(a){this._database.compact(this._id.substr(8),a)},i.prototype.list=function(a,b){return b&&this.body("lists",a,b===null?undefined:b),b!==undefined?this:this._body.lists?this._body.lists[a]:undefined},i.prototype.show=function(a,b){return typeof b!==undefined&&this.body("shows",a,b===null?undefined:b),b!==undefined?this:this._body.shows?this._body.shows[a]:undefined},i.prototype.view=function(a,b,c){var d={};return c&&(d.reduce=c),b!==undefined&&(d.map=b,this.body("views",a,b===null?undefined:d)),b!==undefined?this:this._body.views?this._body.views[a]:undefined},i.prototype.viewInfo=function(a){this._connection.request({method:"GET",path:this._database.name()+"/"+this._id+"/_info",callback:a})},c.Design=i}),a.define("/user.js",function(a,b,c,d,e,f){var g=a("crypto"),h=function(a){this._connection=a};h.prototype.addRole=function(a,b,c){var d=typeof b=="string"?[b]:b;this._connection.database("_users").document("org.couchdb.user:"+a).load(function(a,b){b.body("roles",b.body("roles").concat(d)).save(function(a,b){c(a,a?null:!0)})})},h.prototype.create=function(a,b,c,d){var e=typeof c=="object"?c:[],d=d||c,f;this._lower120(function(c,g){c?d(c,null):g===!0?(f=this._salt(),b=this._hash(b,f),this._connection.database("_users").document("org.couchdb.user:"+a).body({name:a,type:"user",roles:e,password_sha:b,salt:f}).save(function(a,b){d(a,a?null:!0)})):this._connection.database("_users").document("org.couchdb.user:"+a).body({name:a,type:"user",roles:e,password:b}).save(function(a,b){d(a,a?null:!0)})}.bind(this))},h.prototype.delete=function(a,b){var c=this._connection.database("_users").document("org.couchdb.user:"+a);c.info(function(a,d){a?b(a,null):c.destroy(function(a,c){b(a,a?null:!0)})})},h.prototype.deleteRole=function(a,b,c){var d=typeof b=="string"?[b]:b;this._connection.database("_users").document("org.couchdb.user:"+a).load(function(a,b){a?c(a,null):b.body("roles",b.body("roles").filter(function(a,b,c){return d.some(function(b,c,d){return b===a})})).save(function(a,b){c(a,a?null:!0)})})},h.prototype.getRoles=function(a,b){this._connection.database("_users").document("org.couchdb.user:"+a).load(function(a,c){b(a,a?null:c.body("roles"))})},h.prototype._hash=function(a,b){return g.createHash("sha1").update(a+b).digest("hex")},h.prototype._salt=function(){return g.randomBytes(16).toString("hex")},h.prototype._lower120=function(a){this._connection.version(function(b,c){b?a(b,null):(c=c.split(".").map(function(a,b,c){return parseInt(a,10)}),a(null,c[0]<1||c[0]===1&&c[1]<2))})},h.prototype.password=function(a,b,c){var d;this._connection.database("_users").document("org.couchdb.user:"+a).load(function(a,e){a?c(a,null):this._lower120(function(a,f){a?c(a,null):(f===!0?(d=this._salt(),b=this._hash(b,d),e.body("password_sha",b).body("salt",d)):e.body("password_sha",undefined).body("salt",undefined).body("password",b),e.save(function(a,b){c(a,a?null:!0)}))}.bind -(this))}.bind(this))},c.User=h}),a.define("crypto",function(a,b,c,d,e,f){b.exports=a("crypto-browserify")}),a.define("/node_modules/crypto-browserify/package.json",function(a,b,c,d,e,f){b.exports={}}),a.define("/node_modules/crypto-browserify/index.js",function(a,b,c,d,e,f){function j(){var a=[].slice.call(arguments).join(" ");throw new Error([a,"we accept pull requests","http://github.com/dominictarr/crypto-browserify"].join("\n"))}var g=a("./sha"),h=a("./rng"),i={sha1:{hex:g.hex_sha1,binary:g.b64_sha1,ascii:g.str_sha1}};c.createHash=function(a){a=a||"sha1",i[a]||j("algorithm:",a,"is not yet supported");var b="",c=i[a];return{update:function(a){return b+=a,this},digest:function(d){d=d||"binary";var e;(e=c[d])||j("encoding:",d,"is not yet supported for algorithm",a);var f=e(b);return b=null,f}}},c.randomBytes=function(a,b){if(!b||!b.call)return h(a);try{b.call(this,undefined,h(a))}catch(c){b(c)}},["createCredentials","createHmac","createCypher","createCypheriv","createDecipher","createDecipheriv","createSign","createVerify","createDeffieHellman","pbkdf2"].forEach(function(a){c[a]=function(){j("sorry,",a,"is not implemented yet")}})}),a.define("/node_modules/crypto-browserify/sha.js",function(a,b,c,d,e,f){function j(a){return y(q(w(a),a.length*i))}function k(a){return z(q(w(a),a.length*i))}function l(a){return x(q(w(a),a.length*i))}function m(a,b){return y(t(a,b))}function n(a,b){return z(t(a,b))}function o(a,b){return x(t(a,b))}function p(){return j("abc")=="a9993e364706816aba3e25717850c26c9cd0d89d"}function q(a,b){a[b>>5]|=128<<24-b%32,a[(b+64>>9<<4)+15]=b;var c=Array(80),d=1732584193,e=-271733879,f=-1732584194,g=271733878,h=-1009589776;for(var i=0;i16&&(c=q(c,a.length*i));var d=Array(16),e=Array(16);for(var f=0;f<16;f++)d[f]=c[f]^909522486,e[f]=c[f]^1549556828;var g=q(d.concat(w(b)),512+b.length*i);return q(e.concat(g),672)}function u(a,b){var c=(a&65535)+(b&65535),d=(a>>16)+(b>>16)+(c>>16);return d<<16|c&65535}function v(a,b){return a<>>32-b}function w(a){var b=Array(),c=(1<>5]|=(a.charCodeAt(d/i)&c)<<32-i-d%32;return b}function x(a){var b="",c=(1<>5]>>>32-i-d%32&c);return b}function y(a){var b=g?"0123456789ABCDEF":"0123456789abcdef",c="";for(var d=0;d>2]>>(3-d%4)*8+4&15)+b.charAt(a[d>>2]>>(3-d%4)*8&15);return c}function z(a){var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",c="";for(var d=0;d>2]>>8*(3-d%4)&255)<<16|(a[d+1>>2]>>8*(3-(d+1)%4)&255)<<8|a[d+2>>2]>>8*(3-(d+2)%4)&255;for(var f=0;f<4;f++)d*8+f*6>a.length*32?c+=h:c+=b.charAt(e>>6*(3-f)&63)}return c}c.hex_sha1=j,c.b64_sha1=k,c.str_sha1=l,c.hex_hmac_sha1=m,c.b64_hmac_sha1=n,c.str_hmac_sha1=o;var g=0,h="",i=8}),a.define("/node_modules/crypto-browserify/rng.js",function(a,b,c,d,e,f){(function(){var a=this,c,d;c=function(a){var b=new Array(a),c;for(var d=0,c;d>>((d&3)<<3)&255;return b};if(a.crypto&&crypto.getRandomValues){var e=new Uint32Array(4);d=function(a){var b=new Array(a);crypto.getRandomValues(e);for(var c=0;c>2]>>>(c&3)*8&255;return b}}b.exports=d||c})()}),a.define("https",function(a,b,c,d,e,f){b.exports=a("http")}),a.define("/cushion.js",function(a,b,c,d,e,f){var g=a("http"),h=a("./config.js"),i=a("./database.js").Database,j=a("./user.js").User,k=function(b,c,d,e,f){f=f||{},this._methodMatch=/^GET|PUT|POST|DELETE|HEAD|COPY$/i,this._options={host:b||h.host,port:c||h.port,username:d||h.username,password:e||h.password,secure:f.secure||h.secure,path:f.path?f.path+"/":h.path},this._options.secure===!0&&(g=a("https"))};k.prototype.activeTasks=function(a){this.request({method:"GET",path:"_active_tasks",callback:a})},k.prototype.config=function(a,b,c,d){var e=typeof a=="string"?a:null,f=typeof b=="string"?b:null,g=typeof c=="string"||typeof c=="number"||c===null?c:undefined,h;d=d||c||b||a,h={method:g!==undefined?g===null?"DELETE":"PUT":"GET",path:"_config"+(e?"/"+e:"")+(f?"/"+f:""),callback:function(a,b){a?b=null:b=g!==undefined?!0:b,d(a,b)}};if(typeof g=="string"||typeof g=="number")h.body='"'+g+'"';this.request(h)},k.prototype.createAdmin=function(a,b,c){this.config("admins",a,b,function(b,d){var e,f;d===!0?(e=this.database("_users"),f=e.document("org.couchdb.user:"+a),f.body("name",a),f.body("type","user"),f.body("roles",[]),f.save(function(a,b){a?c(a,null):c(a,!0)})):c(b,null)}.bind(this))},k.prototype.database=function(a){return new i(a,this)},k.prototype.deleteAdmin=function(a,b){this.config("admins",a,null,function(c,d){var e,f;d===!0?(e=this.database("_users"),f=e.document("org.couchdb.user:"+a),f.load(function(a,c){c?c.destroy(function(a,c){c?b(null,!0):b(a,null)}):b(a,null)})):b(c,null)}.bind(this))},k.prototype.listDatabases=function(a,b){var c=b?a:null;b=b||a,this.request({method:"GET",path:"_all_dbs",callback:function(a,d){a===null&&d!==null&&(c===!0&&(d=d.filter(function(a,b,c){return a[0]!=="_"})),d=d.map(function(a){return this.database(a)},this)),b(a,d)}.bind(this)})},k.prototype.log=function(a,b){var c=arguments.length>1?a:null;b=b||a,this.request({method:"GET",path:"_log"+(c?"?bytes="+c:""),callback:b})},k.prototype._request=function(a,b){var c="";b.on("data",function(a){c+=a}),b.on("end",function(){try{b.headers["content-type"]==="application/json"&&c.length>0&&(c=JSON.parse(c)),b.statusCode===404&&c.length===0&&(c={error:"not_found",reason:"missing"}),a(c.error?c:null,c.error?null:c,b.headers||null)}catch(d){a(d,null,null)}}.bind(this))},k.prototype.request=function(a){var b={host:this._options.host,port:this._options.port,method:typeof a.method=="string"&&a.method.match(this._methodMatch)!==null?a.method:"GET",path:"/"+this._options.path+(a.path||""),auth:this._options.username+":"+this._options.password,headers:a.headers||{}},c;b.headers.Accept=b.headers.Accept||"*/*,application/json",b.headers["Content-Type"]=b.headers["Content-Type"]||"application/json",c=g.request(b,this._request.bind(this,a.callback)),c.on("error",function(b){a.callback(b,null,null)}.bind(this)),a.body&&(typeof a.body=="object"?c.write(JSON.stringify(a.body)):c.write(a.body)),c.end()},k.prototype.restart=function(a){this.request({method:"POST",path:"_restart",callback:function(b,c){b&&b.code==="ECONNRESET"&&(b=null,c=!0),a(b,c)}})},k.prototype.stats=function(a){this.request({method:"GET",path:"_stats",callback:a})},k.prototype.user=function(){return new j(this)},k.prototype.uuids=function(a,b){var c=arguments.length>1?a:null;b=b||a,this.request({method:"GET",path:"_uuids"+(c?"?count="+c:""),callback:function(a,c){c&&(c=c.uuids),b(a,c)}})},k.prototype.version=function(a){this.request({method:"GET",path:"",callback:function(b,c){c!==null&&(c=c.version),a(b,c)}})},c.Connection=k}),a("/cushion.js")})(); \ No newline at end of file diff --git a/package.json b/package.json index 792e559..0df6a3c 100644 --- a/package.json +++ b/package.json @@ -21,15 +21,16 @@ "bugs": { "url": "http://github.com/zoddy/cushion/issues" }, - "devDependencies": { - "mocha": "1.2.x", - "chai": "1.1.x" - }, "main": "./cushion", "engines": { "node": ">=0.6" }, "license": "MIT", - "dependencies": {}, + "devDependencies": { + "chai": "^2.2.0", + "jshint": "^2.6.3", + "jshint-stylish": "^1.0.1", + "mocha": "^2.2.1" + }, "homepage": "http://zoddy.github.com/cushion" } diff --git a/test/testrunner.js b/test/testrunner.js index 7c23752..0cd6b9c 100644 --- a/test/testrunner.js +++ b/test/testrunner.js @@ -20,22 +20,20 @@ cushion.user = cushion.connection.user(); cushion.database = cushion.connection.database(config.database); cushion.document = cushion.database.document(config.document); cushion.design = cushion.database.document('_design/' + config.design); -cushion.design.list( - config.list, - 'function(head, request) {' + - 'var row;' + - 'start({"headers": {"Content-Type": "text/plain"}});' + - 'while(row = getRow()) {send(row.value._id);}' + +cushion.design.list(config.list, [ + 'function(head, request) {', + 'var row;', + 'start({"headers": {"Content-Type": "text/plain"}});', + 'while(row = getRow()) {send(row.value._id);}', '}' -); -cushion.design.show( - config.show, - 'function(document, request) {' + - 'return {' + - 'body: "Hello " + JSON.stringify(request.query) + " " + request.id' + - '};' + +].join(' ')); +cushion.design.show(config.show, [ + 'function(document, request) {', + 'return {', + 'body: "Hello " + JSON.stringify(request.query) + " " + request.id', + '};', '}' -); +].join(' ')); cushion.design.view(config.view, 'function(doc) {emit(doc._id, doc);}'); @@ -65,59 +63,36 @@ cushion.connection.request = (function(properties) { // get tests -require('fs').readdirSync(__dirname).filter( - function(element, index, array) { - return (element.match(/^\d{1}-[a-z]{1,}-test\.js$/) !== null); - } -).sort().forEach(function(fileName, index, files) { +require('fs').readdirSync(__dirname).filter(function(element) { + return (element.match(/^\d{1}-[a-z]{1,}-test\.js$/) !== null); +}).sort().forEach(function(fileName) { tests = tests.concat(require(__dirname + '/' + fileName).tests); }); -// run tests -var testCaller = function() { - var test = tests.shift(), - callpath; - - if (test) { - callpath = test.callpath.split('.'); - - if (test.callback) { - it(test.message, function(done) { - cushion[callpath[0]][callpath[1]].apply( - cushion[callpath[0]], - (test['arguments'] || []).concat([function() { - // error have to be null - expect(arguments[0]).to.be.null; - - // test callback - test.callback.apply( - null, - arguments - ); - - // next test - done(); - testCaller(); - }]) - ); - }); - } else if (test['return']) { - it(test.message, function(done) { - // test callback - test['return'](cushion[callpath[0]][callpath[1]].apply( - cushion[callpath[0]], - test['arguments'] || [] - )); - - // next test - done(); - testCaller(); - }); - } +tests.forEach(function(test) { + var callpath = test.callpath.split('.'); + + if (test.callback) { + it(test.message, function(done) { + cushion[callpath[0]][callpath[1]].apply( + cushion[callpath[0]], + (test['arguments'] || []).concat([function() { + expect(arguments[0]).to.be.null; // error have to be null + test.callback.apply(null, arguments);// test callback + done(); // next test + }]) + ); + }); + } else if (test['return']) { + it(test.message, function(done) { + // test callback + test['return'](cushion[callpath[0]][callpath[1]].apply( + cushion[callpath[0]], + test['arguments'] || [] + )); + + done(); // next test + }); } -}; - - -// start testing -testCaller(); +});