]> git.cworth.org Git - obsolete/notmuch-web/blob - node_modules/express/bin/express
Install the "express" node module via npm
[obsolete/notmuch-web] / 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.3.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 test template.
154  */
155
156 var appTest = [
157     ""
158   , "// Run $ expresso"
159   , ""
160   , "/**"
161   , " * Module dependencies."
162   , " */"
163   , ""
164   , "var app = require('../app')"
165   , "  , assert = require('assert');"
166   , "",
167   , "module.exports = {"
168   , "  'GET /': function(){"
169   , "    assert.response(app,"
170   , "      { url: '/' },"
171   , "      { status: 200, headers: { 'Content-Type': 'text/html; charset=utf-8' }},"
172   , "      function(res){"
173   , "        assert.includes(res.body, '<title>Express</title>');"
174   , "      });"
175   , "  }"
176   , "};"
177 ].join('\n');
178
179 /**
180  * App template.
181  */
182
183 var app = [
184     ''
185   , '/**'
186   , ' * Module dependencies.'
187   , ' */'
188   , ''
189   , 'var express = require(\'express\');'
190   , ''
191   , 'var app = module.exports = express.createServer();'
192   , ''
193   , '// Configuration'
194   , ''
195   , 'app.configure(function(){'
196   , '  app.set(\'views\', __dirname + \'/views\');'
197   , '  app.set(\'view engine\', \':TEMPLATE\');'
198   , '  app.use(express.bodyParser());'
199   , '  app.use(express.methodOverride());{sess}{css}'
200   , '  app.use(app.router);'
201   , '  app.use(express.static(__dirname + \'/public\'));'
202   , '});'
203   , ''
204   , 'app.configure(\'development\', function(){'
205   , '  app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); '
206   , '});'
207   , ''
208   , 'app.configure(\'production\', function(){'
209   , '  app.use(express.errorHandler()); '
210   , '});'
211   , ''
212   , '// Routes'
213   , ''
214   , 'app.get(\'/\', function(req, res){'
215   , '  res.render(\'index\', {'
216   , '    title: \'Express\''
217   , '  });'
218   , '});'
219   , ''
220   , '// Only listen on $ node app.js'
221   , ''
222   , 'if (!module.parent) {'
223   , '  app.listen(3000);'
224   , '  console.log("Express server listening on port %d", app.address().port);'
225   , '}'
226   , ''
227 ].join('\n');
228
229 // Parse arguments
230
231 var args = process.argv.slice(2)
232   , path = '.';
233
234 while (args.length) {
235   var arg = args.shift();
236   switch (arg) {
237     case '-h':
238     case '--help':
239       abort(usage);
240       break;
241     case '-v':
242     case '--version':
243       abort(version);
244       break;
245     case '-s':
246     case '--session':
247     case '--sessions':
248       sessions = true;
249       break;
250     case '-c':
251     case '--css':
252       args.length
253         ? (cssEngine = args.shift())
254         : abort('--css requires an argument');
255       break;
256     case '-t':
257     case '--template':
258       args.length
259         ? (templateEngine = args.shift())
260         : abort('--template requires an argument');
261       break;
262     default:
263         path = arg;
264   }
265 }
266
267 // Generate application
268
269 (function createApplication(path) {
270   emptyDirectory(path, function(empty){
271     if (empty) {
272       createApplicationAt(path);
273     } else {
274       confirm('destination is not empty, continue? ', function(ok){
275         if (ok) {
276           process.stdin.destroy();
277           createApplicationAt(path);
278         } else {
279           abort('aborting');
280         }
281       });
282     }
283   });
284 })(path);
285
286 /**
287  * Create application at the given directory `path`.
288  *
289  * @param {String} path
290  */
291
292 function createApplicationAt(path) {
293   mkdir(path, function(){
294     mkdir(path + '/pids');
295     mkdir(path + '/logs');
296     mkdir(path + '/public/javascripts');
297     mkdir(path + '/public/images');
298     mkdir(path + '/public/stylesheets', function(){
299       switch (cssEngine) {
300         case 'stylus':
301           write(path + '/public/stylesheets/style.styl', stylus);
302           break;
303         case 'less':
304           write(path + '/public/stylesheets/style.less', less);
305           break;
306         case 'sass':
307           write(path + '/public/stylesheets/style.sass', sass);
308           break;
309         default:
310           write(path + '/public/stylesheets/style.css', css);
311       }
312     });
313     mkdir(path + '/views', function(){
314       switch (templateEngine) {
315         case 'ejs':
316           write(path + '/views/layout.ejs', ejsLayout);
317           write(path + '/views/index.ejs', ejsIndex);
318           break;
319         case 'jade':
320           write(path + '/views/layout.jade', jadeLayout);
321           write(path + '/views/index.jade', jadeIndex);
322           break;
323       }
324     });
325     mkdir(path + '/test', function(){
326       write(path + '/test/app.test.js', appTest);
327     });
328
329     // CSS Engine support
330     switch (cssEngine) {
331       case 'sass':
332       case 'less':
333         app = app.replace('{css}', '\n  app.use(express.compiler({ src: __dirname + \'/public\', enable: [\'' + cssEngine + '\'] }));');
334         break;
335       case 'stylus':
336         app = app.replace('{css}', '\n  app.use(require(\'stylus\').middleware({ src: __dirname + \'/public\' }));');
337         break;
338       default:
339         app = app.replace('{css}', '');
340     }
341
342     // Session support
343     app = app.replace('{sess}', sessions
344       ? '\n  app.use(express.cookieParser());\n  app.use(express.session({ secret: \'your secret here\' }));'
345       : '');
346
347     // Template support
348     app = app.replace(':TEMPLATE', templateEngine);
349
350     write(path + '/app.js', app);
351
352     // Suggestions
353     process.on('exit', function(){
354       if (cssEngine) {
355         console.log('   - make sure you have installed %s: \x1b[33m$ npm install %s\x1b[0m'
356           , cssEngine
357           , cssEngine);
358       }
359       console.log('   - make sure you have installed %s: \x1b[33m$ npm install %s\x1b[0m'
360         , templateEngine
361         , templateEngine);
362     });
363   });
364 }
365
366 /**
367  * Check if the given directory `path` is empty.
368  *
369  * @param {String} path
370  * @param {Function} fn
371  */
372
373 function emptyDirectory(path, fn) {
374   fs.readdir(path, function(err, files){
375     if (err && 'ENOENT' != err.code) throw err;
376     fn(!files || !files.length);
377   });
378 }
379
380 /**
381  * echo str > path.
382  *
383  * @param {String} path
384  * @param {String} str
385  */
386
387 function write(path, str) {
388   fs.writeFile(path, str);
389   console.log('   \x1b[36mcreate\x1b[0m : ' + path);
390 }
391
392 /**
393  * Prompt confirmation with the given `msg`.
394  *
395  * @param {String} msg
396  * @param {Function} fn
397  */
398
399 function confirm(msg, fn) {
400   prompt(msg, function(val){
401     fn(/^ *y(es)?/i.test(val));
402   });
403 }
404
405 /**
406  * Prompt input with the given `msg` and callback `fn`.
407  *
408  * @param {String} msg
409  * @param {Function} fn
410  */
411
412 function prompt(msg, fn) {
413   // prompt
414   if (' ' == msg[msg.length - 1]) {
415     process.stdout.write(msg);
416   } else {
417     console.log(msg);
418   }
419
420   // stdin
421   process.stdin.setEncoding('ascii');
422   process.stdin.once('data', function(data){
423     fn(data);
424   }).resume();
425 }
426
427 /**
428  * Mkdir -p.
429  *
430  * @param {String} path
431  * @param {Function} fn
432  */
433
434 function mkdir(path, fn) {
435   exec('mkdir -p ' + path, function(err){
436     if (err) throw err;
437     console.log('   \x1b[36mcreate\x1b[0m : ' + path);
438     fn && fn();
439   });
440 }
441
442 /**
443  * Exit with the given `str`.
444  *
445  * @param {String} str
446  */
447
448 function abort(str) {
449   console.error(str);
450   process.exit(1);
451 }