7 var program = require('commander')
8 , mkdirp = require('mkdirp')
9 , pkg = require('../package.json')
10 , version = pkg.version
18 .usage('[options] [dir]')
19 .option('-s, --sessions', 'add session support')
20 .option('-e, --ejs', 'add ejs engine support (defaults to jade)')
21 .option('-J, --jshtml', 'add jshtml engine support (defaults to jade)')
22 .option('-H, --hogan', 'add hogan.js engine support')
23 .option('-c, --css <engine>', 'add stylesheet <engine> support (less|stylus) (defaults to plain css)')
24 .option('-f, --force', 'force on non-empty directory')
29 var path = program.args.shift() || '.';
37 program.template = 'jade';
38 if (program.ejs) program.template = 'ejs';
39 if (program.jshtml) program.template = 'jshtml';
40 if (program.hogan) program.template = 'hjs';
43 * Routes index template.
52 , 'exports.index = function(req, res){'
53 , ' res.render(\'index\', { title: \'Express\' });'
58 * Routes users template.
64 , ' * GET users listing.'
67 , 'exports.list = function(req, res){'
68 , ' res.send("respond with a resource");'
73 * Jade layout template.
81 , ' link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')'
87 * Jade index template.
95 , ' p Welcome to #{title}'
106 , ' <title><%= title %></title>'
107 , ' <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
110 , ' <h1><%= title %></h1>'
111 , ' <p>Welcome to <%= title %></p>'
117 * JSHTML layout template.
124 , ' <title> @write(title) </title>'
125 , ' <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
134 * JSHTML index template.
138 '<h1>@write(title)</h1>'
139 , '<p>Welcome to @write(title)</p>'
143 * Hogan.js index template.
149 , ' <title>{{ title }}</title>'
150 , ' <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
153 , ' <h1>{{ title }}</h1>'
154 , ' <p>Welcome to {{ title }}</p>'
160 * Default css template.
166 , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;'
175 * Default less template.
181 , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;'
190 * Default stylus template.
196 , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif'
208 , ' * Module dependencies.'
211 , 'var express = require(\'express\');'
212 , 'var routes = require(\'./routes\');'
213 , 'var user = require(\'./routes/user\');'
214 , 'var http = require(\'http\');'
215 , 'var path = require(\'path\');'
217 , 'var app = express();'
219 , '// all environments'
220 , 'app.set(\'port\', process.env.PORT || 3000);'
221 , 'app.set(\'views\', path.join(__dirname, \'views\'));'
222 , 'app.set(\'view engine\', \':TEMPLATE\');'
223 , 'app.use(express.favicon());'
224 , 'app.use(express.logger(\'dev\'));'
225 , 'app.use(express.json());'
226 , 'app.use(express.urlencoded());'
227 , 'app.use(express.methodOverride());{sess}'
228 , 'app.use(app.router);{css}'
229 , 'app.use(express.static(path.join(__dirname, \'public\')));'
231 , '// development only'
232 , 'if (\'development\' == app.get(\'env\')) {'
233 , ' app.use(express.errorHandler());'
236 , 'app.get(\'/\', routes.index);'
237 , 'app.get(\'/users\', user.list);'
239 , 'http.createServer(app).listen(app.get(\'port\'), function(){'
240 , ' console.log(\'Express server listening on port \' + app.get(\'port\'));'
245 // Generate application
247 (function createApplication(path) {
248 emptyDirectory(path, function(empty){
249 if (empty || program.force) {
250 createApplicationAt(path);
252 program.confirm('destination is not empty, continue? ', function(ok){
254 process.stdin.destroy();
255 createApplicationAt(path);
265 * Create application at the given directory `path`.
267 * @param {String} path
270 function createApplicationAt(path) {
272 process.on('exit', function(){
274 console.log(' install dependencies:');
275 console.log(' $ cd %s && npm install', path);
277 console.log(' run the app:');
278 console.log(' $ node app');
282 mkdir(path, function(){
283 mkdir(path + '/public');
284 mkdir(path + '/public/javascripts');
285 mkdir(path + '/public/images');
286 mkdir(path + '/public/stylesheets', function(){
287 switch (program.css) {
289 write(path + '/public/stylesheets/style.less', less);
292 write(path + '/public/stylesheets/style.styl', stylus);
295 write(path + '/public/stylesheets/style.css', css);
299 mkdir(path + '/routes', function(){
300 write(path + '/routes/index.js', index);
301 write(path + '/routes/user.js', users);
304 mkdir(path + '/views', function(){
305 switch (program.template) {
307 write(path + '/views/index.ejs', ejsIndex);
310 write(path + '/views/layout.jade', jadeLayout);
311 write(path + '/views/index.jade', jadeIndex);
314 write(path + '/views/layout.jshtml', jshtmlLayout);
315 write(path + '/views/index.jshtml', jshtmlIndex);
318 write(path + '/views/index.hjs', hoganIndex);
324 // CSS Engine support
325 switch (program.css) {
327 app = app.replace('{css}', eol + 'app.use(require(\'less-middleware\')({ src: path.join(__dirname, \'public\') }));');
330 app = app.replace('{css}', eol + 'app.use(require(\'stylus\').middleware(path.join(__dirname, \'public\')));');
333 app = app.replace('{css}', '');
337 app = app.replace('{sess}', program.sessions
338 ? eol + 'app.use(express.cookieParser(\'your secret here\'));' + eol + 'app.use(express.session());'
342 app = app.replace(':TEMPLATE', program.template);
346 name: 'application-name'
349 , scripts: { start: 'node app.js' }
355 if (program.template) pkg.dependencies[program.template] = '*';
357 // CSS Engine support
358 switch (program.css) {
360 pkg.dependencies['less-middleware'] = '~0.1.15';
364 pkg.dependencies[program.css] = '*';
368 write(path + '/package.json', JSON.stringify(pkg, null, 2));
369 write(path + '/app.js', app);
374 * Check if the given directory `path` is empty.
376 * @param {String} path
377 * @param {Function} fn
380 function emptyDirectory(path, fn) {
381 fs.readdir(path, function(err, files){
382 if (err && 'ENOENT' != err.code) throw err;
383 fn(!files || !files.length);
390 * @param {String} path
391 * @param {String} str
394 function write(path, str) {
395 fs.writeFile(path, str);
396 console.log(' \x1b[36mcreate\x1b[0m : ' + path);
402 * @param {String} path
403 * @param {Function} fn
406 function mkdir(path, fn) {
407 mkdirp(path, 0755, function(err){
409 console.log(' \033[36mcreate\033[0m : ' + path);
415 * Exit with the given `str`.
417 * @param {String} str
420 function abort(str) {