Changeset 464
- Timestamp:
- 06/23/13 21:46:11 (12 years ago)
- Location:
- Dev/trunk
- Files:
-
- 1 added
- 10 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
Dev/trunk/Gruntfile.js
r463 r464 1 /*************************************** 2 * This Gruntfile is organized with two phases, 3 * compile and build. Compile will lint HTML, 4 * JavaScript and compile LESS. The build phase 5 * creates an optimized stand-alone build that 6 * can be distributed. 1 /** Gruntfile - control build and deploy tasks 7 2 */ 8 3 9 4 module.exports = function(grunt) { 10 5 6 var srcDir = 'src/'; 11 7 var buildDir = 'build/'; 12 var srcDir = 'src/'; 8 var developmentDir = buildDir+'development/'; 9 var productionDir = buildDir+'production/'; 13 10 14 11 grunt.initConfig({ 15 12 clean: { 16 build: { 17 src: [buildDir] 13 development: { 14 src: [developmentDir] 15 }, 16 production: { 17 src: [productionDir] 18 18 } 19 19 }, … … 27 27 cwd: srcDir, 28 28 src: ['client/qed-client/**/*.coffee', 'server/**/*.coffee'], 29 dest: buildDir,29 dest: developmentDir, 30 30 ext: '.js' 31 31 }] … … 33 33 }, 34 34 copy: { 35 'client-deps': { 36 files: [{ 37 expand: true, 38 cwd: srcDir, 39 src: ['client/dojo/**', 'client/dijit/**', 'client/dojox/**', 'client/util/**'], 40 dest: developmentDir 41 }] 42 }, 43 'server-deps': { 44 files: [{ 45 expand: true, 46 cwd: srcDir, 47 src: ['node_modules/**'], 48 dest: developmentDir 49 }] 50 }, 35 51 compile: { 36 52 files: [{ 37 src: [srcDir+'**', '!**/*.coffee' ], 38 dest: buildDir 53 expand: true, 54 cwd: srcDir, 55 src: ['**', '!**/*.coffee', '!**/*.less', '!node_modules/**', '!client/dojo/**', '!client/dijit/**', '!client/dojox/**', '!client/util/**' ], 56 dest: developmentDir 57 }] 58 }, 59 deploy: { 60 files: [{ 61 expand: true, 62 cwd: developmentDir, 63 src: ['**', '!client/*/**' ], 64 dest: productionDir 39 65 }] 40 66 } 41 67 }, 42 68 dojo: { 43 options: { 44 dojo: srcDir+'client/dojo/dojo.js' 45 }, 46 build: { 69 deploy: { 47 70 options: { 48 profile: srcDir+'client/client.profile.js', 49 releaseDir: buildDir 71 dojo: developmentDir+'client/dojo/dojo.js', 72 profile: developmentDir+'client/client.profile.js', 73 releaseDir: '../../../'+productionDir 50 74 } 51 75 } … … 85 109 cwd: srcDir, 86 110 src: ['client/qed-client/css/qed.less'], 87 dest: buildDir,111 dest: developmentDir, 88 112 ext: '.css' 89 113 }] … … 97 121 grunt.loadNpmTasks('grunt-contrib-jshint'); 98 122 grunt.loadNpmTasks('grunt-contrib-less'); 99 grunt.loadNpmTasks('grunt-curl');100 123 grunt.loadNpmTasks('grunt-dojo'); 101 124 grunt.loadNpmTasks('grunt-htmlhint'); 102 grunt.loadNpmTasks('grunt-zip');103 125 126 // development tasks 127 grunt.registerTask('install-deps', ['copy:server-deps', 'copy:client-deps']); 104 128 grunt.registerTask('compile', ['less:compile', 'jshint:compile', 'htmlhint:compile', 'coffee:compile', 'copy:compile']); 105 grunt.registerTask('build', ['clean:build', 'compile', 'dojo:build']); 106 grunt.registerTask('deploy', []); 129 grunt.registerTask('build', ['clean:development', 'install-deps', 'compile']); 130 131 // production tasks 132 grunt.registerTask('deploy', ['clean:production', 'copy:deploy', 'dojo:deploy']); 133 134 // default task is quick compile 107 135 grunt.registerTask('default', ['compile']); 108 136 -
Dev/trunk/README.md
r463 r464 1 === 2 QED 3 === 1 # QED 4 2 5 Install 6 ------- 3 This document describes how to develop this code base and the source 4 code organisation. 7 5 8 - Install CouchDB 9 - Install Node.js 10 - 6 ## Development, Install and Deploy 11 7 8 Source files are located in `src`. Build and deployment is managed 9 with _Grunt_, a node based task runner. 10 11 First make sure _node_, _npm_ and _couchdb_ are installed. Then 12 install all dependencies by running `npm install`. To run _grunt_, 13 you'll have to install the commandline client with `npm install -g 14 grunt-cli`. 15 16 From source to a deployable version goes in few steps. 17 1. Develop in `src`. 18 1. Create a development version with `grunt build`. This will put a 19 complete uncompressed version in `build/development`. 20 1. Run the development version with `node server/standalone.js` or 21 `foreman start`. For the last option, you have to have the Heroku 22 chain installed. 23 1. When editing more files, you can skip copying the fixed 24 dependencies and only process our own source files by running 25 `grunt compile`. If dependencies change (e.g. you installed node 26 modules) or you have the feeling something is weird, just do a 27 clean build by running `grunt build` again. Don't forget to 28 restart the server. 29 1. When you feel your changes are production ready, create a 30 production version by running `grunt deploy`. This will do a 31 _Dojo_ build on the client, creating compressed CSS and 32 Javascript. 33 1. You can test this version with the same commands as the 34 development version, but now from the `build/production` 35 directory. You can distribute the content is this directory as a 36 release. 37 1. If you want to deploy to Heroku, do the following: 38 ```sh 39 $ git clone git@heroku.com:quod-erat.git build/quod-erat 40 $ cd build/quod-erat 41 $ rm -rf * 42 cp -r ../production/* . 43 git add . 44 git commit -a -m "Something informative goes here..." 45 git push 46 ``` 12 47 13 48 File organisation 14 49 ----------------- 50 51 * _/_ Project root 52 * _build/_ Builds go here 53 * _development/_ Uncompressed build 54 * _production/_ Minified build 55 * _docs/_ Project documentation, design documents etc 56 * _src/_ Source code 57 * _client/_ Dojo web client 58 * _server/_ Node/Express server 59 * _Procfile_ Heroku process description 60 61 ``` 15 62 client/ 16 63 The web application for QED. … … 66 113 Contains general widgets that are used in our application but do 67 114 not depend on our model. 68 rx/69 Rx.JS reactive framework for Javascript70 rx.dojo.js71 Custom file to integrate Rx with Dojo.72 115 util/ 73 116 Dojo utils (e.g. build infrastructure) 117 ``` -
Dev/trunk/package.json
r463 r464 12 12 "grunt-htmlhint": "~0.4.0", 13 13 "grunt-contrib-clean": "~0.4.1", 14 "grunt-zip": "~0.9.0", 15 "grunt-curl": "~1.1.0", 16 "grunt-contrib-coffee": "~0.7.0" 14 "grunt-contrib-coffee": "~0.7.0", 15 "underscore": "~1.4.4" 17 16 } 18 17 } -
Dev/trunk/src/.jshintrc
r443 r464 11 11 "unused": false, 12 12 "strict": false, 13 "laxcomma": true, 13 14 14 15 "loopfunc": true, -
Dev/trunk/src/client/qed-client/store/request.js
r463 r464 10 10 var dfd = new Deferred(); 11 11 if ( authenticated ) { 12 request(url,options).response.then(function(response){ 13 console.log(response); 14 }, function(error){ 12 var req = request(url,options); 13 14 // forward successfull response 15 req.then(function(data){ 16 dfd.resolve(data); 17 }); 18 19 req.response.then(function(response){ 20 // if we are recovering, launch other requests 21 }, function(error) { 15 22 if ( error.response.status === 401 ) { 16 23 queue.push({ -
Dev/trunk/src/package.json
r463 r464 4 4 "description": "QED Server", 5 5 "dependencies": { 6 "simple-http-proxy": "~0.5.2",7 6 "express": "~3.2.3", 8 7 "underscore": "~1.4.4", 9 8 "passport": "~0.1.17", 10 "passport-local": "~0.1.6" 9 "passport-local": "~0.1.6", 10 "q": "~0.9.6", 11 "q-io": "~1.9.1" 11 12 }, 12 13 "engines": { -
Dev/trunk/src/server/app.js
r463 r464 4 4 var fs = require("fs"); 5 5 var path = require("path"); 6 var proxy = require(" simple-http-proxy");6 var proxy = require("./simple-http-proxy"); 7 7 var _ = require("underscore"); 8 8 … … 58 58 // url to login (might work on others as well?) 59 59 // you should then have a session to work with 60 app.post('/api/login' , passport.authenticate('local'));60 app.post('/api/login'); 61 61 62 62 // forward to couch 63 app.use('/data/couch', p assport.authenticate('local'), proxy(settings.couchDbURL));63 app.use('/data/couch', proxy(settings.couchDbURL)); 64 64 65 65 return app; -
Dev/trunk/src/server/config/config-couchdb.js
r460 r464 1 1 var q = require('q'); 2 var http= require('q-io/http');3 var fs = require('q-io/fs');2 var HTTP = require('q-io/http'); 3 var URL = require('url'); 4 4 var _ = require('underscore'); 5 var util = require('util'); 5 6 6 var dbURL = "http://localhost:5984/";7 7 var designDocs = require('./couchdb-design-docs'); 8 8 9 function stringifyFunctions(value) { 10 if ( value === null ) { 11 return null; 12 } else if ( _.isArray(value) ) { 13 return value; 14 } else if ( _.isFunction(value) ) { 15 return value.toString(); 16 } else if ( _.isObject(value) ) { 17 value = _.clone(value); 18 _.each(value, function(propValue, propName){ 19 value[propName] = stringifyFunctions(propValue); 9 module.exports = function(couchDbURL) { 10 11 function stringifyFunctions(value) { 12 if ( value === null ) { 13 return null; 14 } else if ( _.isArray(value) ) { 15 return value; 16 } else if ( _.isFunction(value) ) { 17 return value.toString(); 18 } else if ( _.isObject(value) ) { 19 value = _.clone(value); 20 _.each(value, function(propValue, propName){ 21 value[propName] = stringifyFunctions(propValue); 22 }); 23 return value; 24 } else { 25 return value; 26 } 27 } 28 29 function request(method,path,content) { 30 var url = couchDbURL+path; 31 var parsedURL = URL.parse(url); 32 var options = { 33 url: url, 34 method: method, 35 headers: { 36 'content-type': 'application/json; charset=utf-8', 37 'accept': 'application/json' 38 }, 39 body: { 40 forEach: function(callback) { 41 callback(JSON.stringify(content || {})); 42 } 43 } 44 }; 45 // because q-io doesn't support auth properly, we have to 46 // build the f*ing wheel again. 47 if ( parsedURL.auth ) { 48 var auth = new Buffer(parsedURL.auth).toString("base64"); 49 options.headers.authorization = 'Basic '+auth; 50 } 51 return HTTP.request(options) 52 .then(function(res){ 53 return res.body.read().then(function(content){ 54 return JSON.parse(content.toString() || "{}"); 55 }); 56 },function(res){ 57 return res.body.read().then(function(error){ 58 console.warn(error); // q.all doesn't do errors, so let's show them here 59 return JSON.parse(error.toString() || "{}"); 60 }); 20 61 }); 21 return value;22 } else {23 return value;24 62 } 25 }26 63 27 function request(method,path,content) { 28 var url = dbURL+path; 29 return http.request({ 30 url: url, 31 method: method, 32 headers: { 33 'content-type': 'application/json; charset=utf-8', 34 'accept': 'application/json' 35 }, 36 body: { 37 forEach: function(callback) { 38 callback(JSON.stringify(content || {})); 39 } 64 console.log("Configuring CouchDB for QED"); 65 console.log("Checking CouchDB version"); 66 return request('GET','') 67 .then(function(res){ 68 if (res.version !== "1.2.0" ) { 69 console.log("Found "+res.version+", only tested with CouchDB 1.2.0"); 70 } else { 71 console.log("CouchDB 1.2.0 found"); 40 72 } 41 73 }).then(function(res){ 42 return res.body.read().then(function(content){ 43 return JSON.parse(content); 74 console.log("Checking database 'qed'"); 75 return request('GET','qed') 76 .then(function(res){ 77 console.log("Database 'qed' found."); 78 },function(err){ 79 console.log("Creating database 'qed'"); 80 return request('PUT','qed'); 44 81 }); 45 },function(res){ 46 return res.body.read().then(function(error){ 47 return JSON.parse(error); 48 }); 82 }).then(function(){ 83 console.log("Putting documents in database."); 84 designDocs = stringifyFunctions(designDocs); 85 return q.all(_.map(designDocs, function(doc,docUrl){ 86 var configAction = doc.__configAction; 87 delete doc.__configAction; 88 switch (configAction) { 89 case "ignore": 90 console.log(docUrl+" ignored."); 91 break; 92 case "update": 93 console.log(docUrl+" updating."); 94 return request('GET',docUrl) 95 .then(function(oldDoc){ 96 _.extend(oldDoc,doc); 97 return request('PUT',docUrl,oldDoc); 98 },function(){ 99 return request('PUT',docUrl,doc); 100 }); 101 break; 102 case "replace": 103 default: 104 console.log(docUrl+" replacing."); 105 return request('GET',docUrl) 106 .then(function(oldDoc){ 107 _.extend(doc,_.pick(oldDoc,'_id','_rev')); 108 return request('PUT',docUrl,doc); 109 },function(){ 110 return request('PUT',docUrl,doc); 111 }); 112 break; 113 } 114 })); 115 }).then(function(){ 116 console.log("Done!"); 117 },function(err){ 118 console.error("ERROR",err,err.stack); 49 119 }); 50 }51 120 52 console.log("Configuring CouchDB for QED"); 53 console.log("Checking CouchDB version"); 54 request('GET','') 55 .then(function(res){ 56 if (res.version !== "1.2.0" ) { 57 console.log("Found "+res.version+", only tested with CouchDB 1.2.0"); 58 } else { 59 console.log("CouchDB 1.2.0 found"); 60 } 61 console.log("Checking database 'qed'"); 62 }).then(function(res){ 63 return request('GET','qed') 64 .then(function(res){ 65 console.log("Database 'qed' found."); 66 },function(err){ 67 console.log("Creating database 'qed'"); 68 return request('PUT','qed'); 69 }); 70 }).then(function(){ 71 console.log("Putting documents in database."); 72 designDocs = stringifyFunctions(designDocs); 73 return q.all(_.map(designDocs, function(doc,docUrl){ 74 var configAction = doc.__configAction; 75 delete doc.__configAction; 76 switch (configAction) { 77 case "ignore": 78 console.log(docUrl+" ignored."); 79 case "update": 80 console.log(docUrl+" updating."); 81 return request('GET',docUrl) 82 .then(function(oldDoc){ 83 _.extend(oldDoc,doc); 84 return request('PUT',docUrl,oldDoc); 85 },function(){ 86 return request('PUT',docUrl,doc); 87 }); 88 case "replace": 89 default: 90 console.log(docUrl+" replacing."); 91 return request('GET',docUrl) 92 .then(function(oldDoc){ 93 _.extend(doc,_.pick(oldDoc,'_id','_rev')); 94 return request('PUT',docUrl,doc); 95 },function(){ 96 return request('PUT',docUrl,doc); 97 }); 98 } 99 })); 100 }).then(function(){ 101 console.log("Done!"); 102 },function(err){ 103 console.error("ERROR",err); 104 }); 121 }; -
Dev/trunk/src/server/config/couchdb-design-docs.js
r455 r464 1 1 module.exports = { 2 2 3 "_users/qed_admin": { 3 4 __configAction: "ignore", … … 8 9 type: "user" 9 10 }, 11 10 12 "qed/_security": { 11 13 __configAction: "ignore", … … 19 21 } 20 22 }, 23 21 24 "qed/_design/default": { 22 25 __configAction: "replace", … … 34 37 } 35 38 }, 39 36 40 "qed/_design/questions": { 37 41 __configAction: "replace", … … 81 85 } 82 86 }, 87 83 88 "qed/_design/surveys": { 84 89 __configAction: "replace", … … 100 105 } 101 106 }, 107 102 108 "qed/_design/responses": { 103 109 __configAction: "replace", … … 113 119 } 114 120 } 121 115 122 }; -
Dev/trunk/src/server/heroku.js
r463 r464 1 var app = require('./app').App({ 2 couchDbURL: 'http://localhost:5984/qed' 1 var port = process.env.PORT || 5000; 2 var couchDbURL = (process.env.CLOUDANT_URL || 'http://localhost:5984')+'/'; 3 4 var configCouch = require('./config/config-couchdb'); 5 6 configCouch(couchDbURL) 7 .then(function(){ 8 var app = require('./app').App({ 9 couchDbURL: couchDbURL+'qed' 10 }); 11 12 app.listen(port, function() { 13 console.log('Listening on port',port); 14 }); 3 15 }); 4 5 var port = process.env.PORT || 5000;6 app.listen(port, function() {7 console.log('Listening on port',port);8 }); -
Dev/trunk/src/server/standalone.js
r463 r464 2 2 var https = require("https"); 3 3 var os = require("os"); 4 var path = require("path");5 4 var _ = require("underscore"); 6 5 … … 10 9 11 10 var httpsOptions = { 12 key: fs.readFileSync( path.resolve('../qed-server.key')),13 cert: fs.readFileSync( path.resolve('../qed-server.pem'))11 key: fs.readFileSync(__dirname+'/../qed-server.key'), 12 cert: fs.readFileSync(__dirname+'/../qed-server.pem') 14 13 }; 15 14
Note: See TracChangeset
for help on using the changeset viewer.