commit dc8a82b42d9f210d01e31c8faf1823194e21b364 Author: Ken Elf Mathieu Sternberg Date: Thu Aug 9 18:34:00 2012 -0700 Initial check-in. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..db3f887 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*# +.#* +*~ +npm-debug.log +node_modules/* diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..2ccbe46 --- /dev/null +++ b/.npmignore @@ -0,0 +1 @@ +/node_modules/ diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..17416f9 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2012 Ken Elf Mathieu Sternberg + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..17a8101 --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +# grunt-couchapp + +A grunt plugin for building and installing couchapps + +## Getting Started Install this grunt plugin next to your project's +[grunt.js gruntfile][getting_started] with: `npm install +grunt-couchapp` + +Then add this line to your project's `grunt.js` gruntfile: + +```javascript +grunt.loadNpmTasks('grunt-couchapp'); +``` + +[grunt]: https://github.com/cowboy/grunt +[getting_started]: https://github.com/cowboy/grunt/blob/master/docs/getting_started.md + +## Documentation + +You'll want to add some configuration for the plug-in. This plugin +provides three tasks, *mkcouchdb* to create new databases, *rmcouchdb* +to delete all data and drop an existing database, and *couchapp*, +which installs a specified couchapp into the database. + + mkcouchdb: { + demo: { + db: 'http://localhost:5984/grunt-couchapp-demo' + } + }, + + rmcouchdb: { + demo: { + db: 'http://localhost:5984/grunt-couchapp-demo', + options: { + okay_if_missing: true + } + } + }, + + couchapp: { + demo: { + db: 'http://localhost:5984/grunt-couchapp-demo', + app: './demo/app.js' + } + } + +As a stylistic note, all of the commands take the same info, so it's +possible to write in your configuration file: + + couch_config = { + demo: { + db: 'http://localhost:5984/grunt-couchapp-demo', + app: './demo/app.js', + options: { + okay_if_missing: true + } + } + } + + grunt.initConfig({ + ... + mkcouchdb: couch_config, + rmcouchdb: couch_config, + couchapp: couch_config, + ... + }); + + +Note, however, that if you call 'rmcouchdb' without a sub-argument, in +keeping with grunt's standards, it will drop *all* of your databases! + +## Contributing + +In lieu of a formal styleguide, take care to maintain the existing +coding style. Add unit tests for any new or changed +functionality. Lint and test your code using [grunt][grunt]. + +## License +Copyright (c) 2012 Ken Elf Mathieu Sternberg +Licensed under the MIT license. diff --git a/bin/grunt-couchapp b/bin/grunt-couchapp new file mode 100644 index 0000000..e9e41ed --- /dev/null +++ b/bin/grunt-couchapp @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('grunt').npmTasks('grunt-couchapp').cli(); diff --git a/demo/app.js b/demo/app.js new file mode 100644 index 0000000..09a6391 --- /dev/null +++ b/demo/app.js @@ -0,0 +1,22 @@ +var couchapp, ddoc, path; + +couchapp = require('couchapp'); + +path = require('path'); + +ddoc = { + _id: '_design/app', + rewrites: {}, + views: {}, + shows: {}, + lists: {}, + validate_doc_update: function(newDoc, oldDoc, userCtx) { + if (newDoc._deleted === true && userCtx.roles.indexOf('_admin') === -1) { + throw "Only admin can delete documents on this database."; + } + } +}; + +couchapp.loadAttachments(ddoc, path.join(__dirname, 'attachments')); + +module.exports = ddoc; diff --git a/demo/attachments/index.html b/demo/attachments/index.html new file mode 100644 index 0000000..7be5406 --- /dev/null +++ b/demo/attachments/index.html @@ -0,0 +1,15 @@ + + + + + + + + Demo + + +

Demonstration

+

Congratulations! You have installed + grunt-couchapp correctly.

+ + diff --git a/grunt.js b/grunt.js new file mode 100644 index 0000000..0e3ad16 --- /dev/null +++ b/grunt.js @@ -0,0 +1,61 @@ +var DEMO_COUCH_DB = 'http://localhost:5984/grunt-couchapp-demo'; + +module.exports = function(grunt) { + // Project configuration. + + grunt.initConfig({ + + test: { + files: ['test/**/*.js'] + }, + lint: { + files: ['grunt.js', 'tasks/**/*.js', 'test/**/*.js'] + }, + watch: { + files: '', + tasks: 'default' + }, + jshint: { + options: { + curly: true, + eqeqeq: true, + immed: true, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + boss: true, + eqnull: true, + node: true, + es5: true + }, + globals: {} + }, + mkcouchdb: { + demo: { + db: DEMO_COUCH_DB + } + }, + rmcouchdb: { + demo: { + db: DEMO_COUCH_DB, + options: { + okay_if_missing: true + } + } + }, + couchapp: { + demo: { + db: DEMO_COUCH_DB, + app: './demo/app.js' + } + } + }); + + // Load local tasks. + grunt.loadTasks('tasks'); + + // Default task. + grunt.registerTask('default', 'lint test'); +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..8fb8f01 --- /dev/null +++ b/package.json @@ -0,0 +1,43 @@ +{ + "name": "grunt-couchapp", + "description": "A grunt plugin for building and uploading couchapps", + "version": "0.1.0", + "homepage": "https://github.com/elf/grunt-couchapp", + "author": { + "name": "Ken Elf Mathieu Sternberg", + "email": "elf.sternberg@gmail.com", + "url": "http://elfsternberg.com" + }, + "repository": { + "type": "git", + "url": "git://github.com/elf/grunt-couchapp.git" + }, + "bugs": { + "url": "https://github.com/elf/grunt-couchapp/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/elf/grunt-couchapp/blob/master/LICENSE-MIT" + } + ], + "main": "grunt.js", + "bin": "bin/grunt-couchapp", + "engines": { + "node": "*" + }, + "scripts": { + "test": "grunt test" + }, + "dependencies": { + "couchapp": "0.9.1", + "grunt": "~0.3.12", + "nano": "3.3.0" + }, + "devDependencies": { + "grunt": "~0.3.12" + }, + "keywords": [ + "gruntplugin" + ] +} \ No newline at end of file diff --git a/tasks/couchapp.js b/tasks/couchapp.js new file mode 100644 index 0000000..e28a6bb --- /dev/null +++ b/tasks/couchapp.js @@ -0,0 +1,78 @@ +/* + * grunt-couchapp https://github.com/elf/grunt-couchapp + * + * Copyright (c) 2012 Ken "Elf" Mathieu Sternberg + * Licensed under the MIT license. + */ + +var path, couchapp, nanolib, urls; + +path = require('path'); +couchapp = require('couchapp'); +urls = require('url'); + +module.exports = function(grunt) { + + // ========================================================================== + // TASKS + // ========================================================================== + + grunt.registerMultiTask("couchapp", "Install Couchapp", function() { + var appobj, done; + done = this.async(); + appobj = require(path.join(process.cwd(), path.normalize(this.data.app))); + return couchapp.createApp(appobj, this.data.db, function(app) { + return app.push(done); + }); + }); + + grunt.registerMultiTask("rmcouchdb", "Delete a Couch Database", function() { + var done, parts, nano, dbname, _this; + _this = this; + done = this.async(); + parts = urls.parse(this.data.db); + dbname = parts.pathname.replace(/^\//, ''); + try { + nano = require('nano')(parts.protocol + '//' + parts.host); + nano.db.destroy(dbname, function(err) { + if (err) { + if (err.status_code && err.status_code === 404) { + if (_this.data.options && _this.data.options.okay_if_missing) { + grunt.log.writeln("Database " + dbname + " not present... skipping."); + return done(null, null) ; + } else { + grunt.warn("Database " + dbname + " does not exist."); + } + } else { + grunt.warn(err); + } + } + return done(err, null); + }); + } catch (e) { + grunt.warn(e); + done(e, null); + } + }); + + grunt.registerMultiTask("mkcouchdb", "Delete a Couch Database", function() { + var done, parts, nano, dbname; + + done = this.async(); + parts = urls.parse(this.data.db); + dbname = parts.pathname.replace(/^\//, ''); + try { + nano = require('nano')(parts.protocol + '//' + parts.host); + nano.db.create(dbname, function(err) { + if (err) { + grunt.warn(err); + } + return done(err, null); + }); + } catch (e) { + grunt.warn(e); + done(e, null); + } + }); + +}; diff --git a/test/couchapp_test.js b/test/couchapp_test.js new file mode 100644 index 0000000..d1a4f62 --- /dev/null +++ b/test/couchapp_test.js @@ -0,0 +1,27 @@ +var grunt = require('grunt'); + +/* + ======== A Handy Little Nodeunit Reference ======== + https://github.com/caolan/nodeunit + + Test methods: + test.expect(numAssertions) + test.done() + Test assertions: + test.ok(value, [message]) + test.equal(actual, expected, [message]) + test.notEqual(actual, expected, [message]) + test.deepEqual(actual, expected, [message]) + test.notDeepEqual(actual, expected, [message]) + test.strictEqual(actual, expected, [message]) + test.notStrictEqual(actual, expected, [message]) + test.throws(block, [error], [message]) + test.doesNotThrow(block, [error], [message]) + test.ifError(value) +*/ + +exports.couchapp = { + setUp: function(done) { + done(); + } +};