Inital Commit
[oweals/finalsclub.git] / bruml / node_modules / express / bin / express
1 #!/usr/bin/env node
2
3 /**
4  * Module dependencies.
5  */
6
7 var fs = require('fs')
8   , exec = require('child_process').exec;
9
10 /**
11  * Framework version.
12  */
13
14 var version = '2.4.3';
15
16 /**
17  * Add session support.
18  */
19
20 var sessions = false;
21
22 /**
23  * CSS engine to utilize.
24  */
25
26 var cssEngine;
27
28 /**
29  * Template engine to utilize.
30  */
31
32 var templateEngine = 'jade';
33
34 /**
35  * Usage documentation.
36  */
37
38 var usage = ''
39   + '\n'
40   + '  Usage: express [options] [path]\n'
41   + '\n'
42   + '  Options:\n'
43   + '    -s, --sessions           add session support\n'
44   + '    -t, --template <engine>  add template <engine> support (jade|ejs). default=jade\n'
45   + '    -c, --css <engine>       add stylesheet <engine> support (less|sass|stylus). default=plain css\n'
46   + '    -v, --version            output framework version\n'
47   + '    -h, --help               output help information\n'
48   ;
49
50 /**
51  * Jade layout template.
52  */
53
54 var jadeLayout = [
55     '!!!'
56   , 'html'
57   , '  head'
58   , '    title= title'
59   , '    link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')'
60   , '  body!= body'
61 ].join('\n');
62
63 /**
64  * Jade index template.
65  */
66
67 var jadeIndex = [
68     'h1= title'
69   , 'p Welcome to #{title}'
70 ].join('\n');
71
72 /**
73  * EJS layout template.
74  */
75
76 var ejsLayout = [
77     '<!DOCTYPE html>'
78   , '<html>'
79   , '  <head>'
80   , '    <title><%= title %></title>'
81   , '    <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
82   , '  </head>'
83   , '  <body>'
84   , '    <%- body %>'
85   , '  </body>'
86   , '</html>'
87 ].join('\n');
88
89 /**
90  * EJS index template.
91  */
92
93 var ejsIndex = [
94     '<h1><%= title %></h1>'
95   , '<p>Welcome to <%= title %></p>'
96   ].join('\n');
97
98 /**
99  * Default css template.
100  */
101
102 var css = [
103     'body {'
104   , '  padding: 50px;'
105   , '  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;'
106   , '}'
107   , ''
108   , 'a {'
109   , '  color: #00B7FF;'
110   , '}'
111 ].join('\n');
112
113 /**
114  * Default less template.
115  */
116
117 var less = [
118     'body {'
119   , '  padding: 50px;'
120   , '  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;'
121   , '}'
122   , ''
123   , 'a {'
124   , '  color: #00B7FF;'
125   , '}'
126 ].join('\n');
127
128 /**
129  * Default sass template.
130  */
131
132 var sass = [
133     'body'
134   , '  :padding 50px'
135   , '  :font 14px "Lucida Grande", Helvetica, Arial, sans-serif'
136   , 'a'
137   , '  :color #00B7FF'
138 ].join('\n');
139
140 /**
141  * Default stylus template.
142  */
143
144 var stylus = [
145     'body'
146   , '  padding 50px'
147   , '  font 14px "Lucida Grande", Helvetica, Arial, sans-serif'
148   , 'a'
149   , '  color #00B7FF'
150 ].join('\n');
151
152 /**
153  * App template.
154  */
155
156 var app = [
157     ''
158   , '/**'
159   , ' * Module dependencies.'
160   , ' */'
161   , ''
162   , 'var express = require(\'express\');'
163   , ''
164   , 'var app = module.exports = express.createServer();'
165   , ''
166   , '// Configuration'
167   , ''
168   , 'app.configure(function(){'
169   , '  app.set(\'views\', __dirname + \'/views\');'
170   , '  app.set(\'view engine\', \':TEMPLATE\');'
171   , '  app.use(express.bodyParser());'
172   , '  app.use(express.methodOverride());{sess}{css}'
173   , '  app.use(app.router);'
174   , '  app.use(express.static(__dirname + \'/public\'));'
175   , '});'
176   , ''
177   , 'app.configure(\'development\', function(){'
178   , '  app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); '
179   , '});'
180   , ''
181   , 'app.configure(\'production\', function(){'
182   , '  app.use(express.errorHandler()); '
183   , '});'
184   , ''
185   , '// Routes'
186   , ''
187   , 'app.get(\'/\', function(req, res){'
188   , '  res.render(\'index\', {'
189   , '    title: \'Express\''
190   , '  });'
191   , '});'
192   , ''
193   , 'app.listen(3000);'
194   , 'console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);'
195   , ''
196 ].join('\n');
197
198 // Parse arguments
199
200 var args = process.argv.slice(2)
201   , path = '.';
202
203 while (args.length) {
204   var arg = args.shift();
205   switch (arg) {
206     case '-h':
207     case '--help':
208       abort(usage);
209       break;
210     case '-v':
211     case '--version':
212       abort(version);
213       break;
214     case '-s':
215     case '--session':
216     case '--sessions':
217       sessions = true;
218       break;
219     case '-c':
220     case '--css':
221       args.length
222         ? (cssEngine = args.shift())
223         : abort('--css requires an argument');
224       break;
225     case '-t':
226     case '--template':
227       args.length
228         ? (templateEngine = args.shift())
229         : abort('--template requires an argument');
230       break;
231     default:
232         path = arg;
233   }
234 }
235
236 // Generate application
237
238 (function createApplication(path) {
239   emptyDirectory(path, function(empty){
240     if (empty) {
241       createApplicationAt(path);
242     } else {
243       confirm('destination is not empty, continue? ', function(ok){
244         if (ok) {
245           process.stdin.destroy();
246           createApplicationAt(path);
247         } else {
248           abort('aborting');
249         }
250       });
251     }
252   });
253 })(path);
254
255 /**
256  * Create application at the given directory `path`.
257  *
258  * @param {String} path
259  */
260
261 function createApplicationAt(path) {
262   mkdir(path, function(){
263     mkdir(path + '/public/javascripts');
264     mkdir(path + '/public/images');
265     mkdir(path + '/public/stylesheets', function(){
266       switch (cssEngine) {
267         case 'stylus':
268           write(path + '/public/stylesheets/style.styl', stylus);
269           break;
270         case 'less':
271           write(path + '/public/stylesheets/style.less', less);
272           break;
273         case 'sass':
274           write(path + '/public/stylesheets/style.sass', sass);
275           break;
276         default:
277           write(path + '/public/stylesheets/style.css', css);
278       }
279     });
280     mkdir(path + '/views', function(){
281       switch (templateEngine) {
282         case 'ejs':
283           write(path + '/views/layout.ejs', ejsLayout);
284           write(path + '/views/index.ejs', ejsIndex);
285           break;
286         case 'jade':
287           write(path + '/views/layout.jade', jadeLayout);
288           write(path + '/views/index.jade', jadeIndex);
289           break;
290       }
291     });
292
293     // CSS Engine support
294     switch (cssEngine) {
295       case 'sass':
296       case 'less':
297         app = app.replace('{css}', '\n  app.use(express.compiler({ src: __dirname + \'/public\', enable: [\'' + cssEngine + '\'] }));');
298         break;
299       case 'stylus':
300         app = app.replace('{css}', '\n  app.use(require(\'stylus\').middleware({ src: __dirname + \'/public\' }));');
301         break;
302       default:
303         app = app.replace('{css}', '');
304     }
305
306     // Session support
307     app = app.replace('{sess}', sessions
308       ? '\n  app.use(express.cookieParser());\n  app.use(express.session({ secret: \'your secret here\' }));'
309       : '');
310
311     // Template support
312     app = app.replace(':TEMPLATE', templateEngine);
313
314     // package.json
315     var json = '{\n';
316     json += '    "name": "application-name"\n';
317     json += '  , "version": "0.0.1"\n';
318     json += '  , "private": true\n';
319     json += '  , "dependencies": {\n';
320     json += '      "express": "' + version + '"\n';
321     if (cssEngine) json += '    , "' + cssEngine + '": ">= 0.0.1"\n';
322     if (templateEngine) json += '    , "' + templateEngine + '": ">= 0.0.1"\n';
323     json += '  }\n';
324     json += '}';
325
326
327     write(path + '/package.json', json);
328     write(path + '/app.js', app);
329   });
330 }
331
332 /**
333  * Check if the given directory `path` is empty.
334  *
335  * @param {String} path
336  * @param {Function} fn
337  */
338
339 function emptyDirectory(path, fn) {
340   fs.readdir(path, function(err, files){
341     if (err && 'ENOENT' != err.code) throw err;
342     fn(!files || !files.length);
343   });
344 }
345
346 /**
347  * echo str > path.
348  *
349  * @param {String} path
350  * @param {String} str
351  */
352
353 function write(path, str) {
354   fs.writeFile(path, str);
355   console.log('   \x1b[36mcreate\x1b[0m : ' + path);
356 }
357
358 /**
359  * Prompt confirmation with the given `msg`.
360  *
361  * @param {String} msg
362  * @param {Function} fn
363  */
364
365 function confirm(msg, fn) {
366   prompt(msg, function(val){
367     fn(/^ *y(es)?/i.test(val));
368   });
369 }
370
371 /**
372  * Prompt input with the given `msg` and callback `fn`.
373  *
374  * @param {String} msg
375  * @param {Function} fn
376  */
377
378 function prompt(msg, fn) {
379   // prompt
380   if (' ' == msg[msg.length - 1]) {
381     process.stdout.write(msg);
382   } else {
383     console.log(msg);
384   }
385
386   // stdin
387   process.stdin.setEncoding('ascii');
388   process.stdin.once('data', function(data){
389     fn(data);
390   }).resume();
391 }
392
393 /**
394  * Mkdir -p.
395  *
396  * @param {String} path
397  * @param {Function} fn
398  */
399
400 function mkdir(path, fn) {
401   exec('mkdir -p ' + path, function(err){
402     if (err) throw err;
403     console.log('   \x1b[36mcreate\x1b[0m : ' + path);
404     fn && fn();
405   });
406 }
407
408 /**
409  * Exit with the given `str`.
410  *
411  * @param {String} str
412  */
413
414 function abort(str) {
415   console.error(str);
416   process.exit(1);
417 }