var fs = require('fs'); var os = require('os'); var blessed = require('blessed'); var multiline = require('multiline'); if (os.platform() === 'win32') { console.log('**************************************************************'); console.log('Hackathon Starter Generator has been disabled on Windows until'); console.log('https://github.com/chjj/blessed is fixed or until I find a'); console.log('better CLI module.'); console.log('**************************************************************'); process.exit(); } var screen = blessed.screen({ autoPadding: true }); screen.key('q', function() { process.exit(0); }); var home = blessed.list({ parent: screen, padding: { top: 2 }, mouse: true, keys: true, fg: 'white', bg: 'blue', selectedFg: 'blue', selectedBg: 'white', items: [ '» REMOVE AUTHENTICATION PROVIDER', '» CHANGE EMAIL SERVICE', '» ADD NODE.JS CLUSTER SUPPORT', '» EXIT' ] }); var homeTitle = blessed.text({ parent: screen, align: 'center', fg: 'blue', bg: 'white', content: 'Hackathon Starter (c) 2014' }); var footer = blessed.text({ parent: screen, bottom: 0, fg: 'white', bg: 'blue', tags: true, content: ' {cyan-fg}{/cyan-fg} moves |' + ' {cyan-fg}{/cyan-fg} selects | {cyan-fg}{/cyan-fg} exits' }); var inner = blessed.form({ top: 'center', left: 'center', mouse: true, keys: true, width: 33, height: 10, border: { type: 'line', fg: 'white', bg: 'red' }, fg: 'white', bg: 'red' }); var success = blessed.box({ top: 'center', left: 'center', mouse: true, keys: true, tags: true, width: '50%', height: '40%', border: { type: 'line', fg: 'white', bg: 'green' }, fg: 'white', bg: 'green', padding: 1 }); success.on('keypress', function() { home.focus(); home.remove(success); }); var clusterText = blessed.text({ top: 'top', bg: 'red', fg: 'white', tags: true, content: 'Take advantage of multi-core systems' + ' using built-in {underline}cluster{/underline} module.' }); var enable = blessed.button({ parent: inner, bottom: 0, mouse: true, shrink: true, name: 'enable', content: ' ENABLE ', border: { type: 'line', fg: 'white', bg: 'red' }, style: { fg: 'white', bg: 'red', focus: { fg: 'red', bg: 'white' } } }); var disable = blessed.button({ parent: inner, bottom: 0, left: 10, mouse: true, shrink: true, name: 'disable', content: ' DISABLE ', border: { type: 'line', fg: 'white', bg: 'red' }, style: { fg: 'white', bg: 'red', focus: { fg: 'red', bg: 'white' } } }); var cancel = blessed.button({ parent: inner, bottom: 0, left: 21, mouse: true, shrink: true, name: 'cancel', content: ' CANCEL ', border: { type: 'line', fg: 'white', bg: 'red' }, style: { fg: 'white', bg: 'red', focus: { fg: 'red', bg: 'white' } } }); cancel.on('press', function() { home.focus(); home.remove(inner); screen.render(); }); var authForm = blessed.form({ mouse: true, keys: true, fg: 'white', bg: 'blue', padding: { left: 1, right: 1 } }); authForm.on('submit', function() { var passportConfig = fs.readFileSync('config/passport.js') .toString().split(os.EOL); var loginTemplate = fs.readFileSync('views/account/login.jade') .toString().split(os.EOL); var profileTemplate = fs.readFileSync('views/account/profile.jade') .toString().split(os.EOL); var userModel = fs.readFileSync('models/User.js').toString().split(os.EOL); var app = fs.readFileSync('app.js').toString().split(os.EOL); var secrets = fs.readFileSync('config/secrets.js').toString().split(os.EOL); var index = passportConfig .indexOf('var FacebookStrategy = require("passport-facebook").Strategy;'); if (facebookCheckbox.checked && index !== -1) { passportConfig.splice(index, 1); index = passportConfig.indexOf('// Sign in with Facebook.'); passportConfig.splice(index, 47); fs.writeFileSync('config/passport.js', passportConfig.join(os.EOL)); index = loginTemplate.indexOf( ' a.btn.btn-block.btn-facebook.btn-social(href="/auth/facebook")' ); loginTemplate.splice(index, 3); fs.writeFileSync('views/account/login.jade', loginTemplate.join(os.EOL)); index = profileTemplate.indexOf(' if user.facebook'); profileTemplate.splice(index - 1, 5); fs.writeFileSync( 'views/account/profile.jade', profileTemplate.join(os.EOL) ); index = userModel.indexOf(' facebook: String,'); userModel.splice(index, 1); fs.writeFileSync('models/User.js', userModel.join(os.EOL)); index = app.indexOf([ 'app.get("/auth/facebook"', 'passport.authenticate("facebook",', ' { scope: ["email", "user_location"] }));' ].join(' ')); app.splice(index, 4); fs.writeFileSync('app.js', app.join(os.EOL)); } index = passportConfig.indexOf( "var GitHubStrategy = require('passport-github').Strategy;" ); if (githubCheckbox.checked && index !== -1) { console.log(index); passportConfig.splice(index, 1); index = passportConfig.indexOf('// Sign in with GitHub.'); passportConfig.splice(index, 48); fs.writeFileSync('config/passport.js', passportConfig.join(os.EOL)); index = loginTemplate.indexOf( " a.btn.btn-block.btn-github.btn-social(href='/auth/github')" ); loginTemplate.splice(index, 3); fs.writeFileSync('views/account/login.jade', loginTemplate.join(os.EOL)); index = profileTemplate.indexOf(' if user.github'); profileTemplate.splice(index - 1, 5); fs.writeFileSync( 'views/account/profile.jade', profileTemplate.join(os.EOL) ); index = userModel.indexOf(' github: String,'); userModel.splice(index, 1); fs.writeFileSync('models/User.js', userModel.join(os.EOL)); index = app.indexOf( 'app.get("/auth/github", passport.authenticate("github"));' ); app.splice(index, 4); fs.writeFileSync('app.js', app.join(os.EOL)); } index = passportConfig.indexOf( 'var GoogleStrategy = require("passport-google-oauth").OAuth2Strategy;' ); if (googleCheckbox.checked && index !== -1) { passportConfig.splice(index, 1); index = passportConfig.indexOf('// Sign in with Google.'); passportConfig.splice(index, 46); fs.writeFileSync('config/passport.js', passportConfig.join(os.EOL)); index = loginTemplate.indexOf( " a.btn.btn-block.btn-google-plus.btn-social(href='/auth/google')" ); loginTemplate.splice(index, 3); fs.writeFileSync('views/account/login.jade', loginTemplate.join(os.EOL)); index = profileTemplate.indexOf(' if user.google'); profileTemplate.splice(index - 1, 5); fs.writeFileSync( 'views/account/profile.jade', profileTemplate.join(os.EOL) ); index = userModel.indexOf(' google: String,'); userModel.splice(index, 1); fs.writeFileSync('models/User.js', userModel.join(os.EOL)); index = app.indexOf( 'app.get("/auth/google",' + ' passport.authenticate("google", { scope: "profile email" }));' ); app.splice(index, 4); fs.writeFileSync('app.js', app.join(os.EOL)); } index = passportConfig.indexOf( 'var TwitterStrategy = require("passport-twitter").Strategy;' ); if (twitterCheckbox.checked && index !== -1) { passportConfig.splice(index, 1); index = passportConfig.indexOf('// Sign in with Twitter.'); passportConfig.splice(index, 43); fs.writeFileSync('config/passport.js', passportConfig.join(os.EOL)); index = loginTemplate.indexOf( ' a.btn.btn-block.btn-twitter.btn-social(href="/auth/twitter")' ); loginTemplate.splice(index, 3); fs.writeFileSync('views/account/login.jade', loginTemplate.join(os.EOL)); index = profileTemplate.indexOf(' if user.twitter'); profileTemplate.splice(index - 1, 5); fs.writeFileSync( 'views/account/profile.jade', profileTemplate.join(os.EOL) ); index = userModel.indexOf(' twitter: String,'); userModel.splice(index, 1); fs.writeFileSync('models/User.js', userModel.join(os.EOL)); index = app.indexOf( "app.get('/auth/twitter', passport.authenticate('twitter'));" ); app.splice(index, 4); fs.writeFileSync('app.js', app.join(os.EOL)); } index = passportConfig.indexOf( 'var LinkedInStrategy = require("passport-linkedin-oauth2").Strategy;' ); if (linkedinCheckbox.checked && index !== -1) { passportConfig.splice(index, 1); index = passportConfig.indexOf('// Sign in with LinkedIn.'); passportConfig.splice(index, 47); fs.writeFileSync('config/passport.js', passportConfig.join(os.EOL)); index = loginTemplate.indexOf( ' a.btn.btn-block.btn-linkedin.btn-social(href="/auth/linkedin")' ); loginTemplate.splice(index, 3); fs.writeFileSync('views/account/login.jade', loginTemplate.join(os.EOL)); index = profileTemplate.indexOf(' if user.linkedin'); profileTemplate.splice(index - 1, 5); fs.writeFileSync( 'views/account/profile.jade', profileTemplate.join(os.EOL) ); index = userModel.indexOf(' linkedin: String,'); userModel.splice(index, 1); fs.writeFileSync('models/User.js', userModel.join(os.EOL)); index = app.indexOf( 'app.get("/auth/linkedin",', ' passport.authenticate("linkedin", { state: "SOME STATE" }));' ); app.splice(index, 4); fs.writeFileSync('app.js', app.join(os.EOL)); } index = passportConfig.indexOf( 'var InstagramStrategy = require("passport-instagram").Strategy;' ); if (instagramCheckbox.checked && index !== -1) { passportConfig.splice(index, 1); index = passportConfig.indexOf('// Sign in with Instagram.'); passportConfig.splice(index, 43); fs.writeFileSync( 'config/passport.js', passportConfig.join(os.EOL) ); index = loginTemplate.indexOf( ' a.btn.btn-block.btn-instagram.btn-social(href="/auth/instagram")' ); loginTemplate.splice(index, 3); fs.writeFileSync( 'views/account/login.jade', loginTemplate.join(os.EOL) ); index = profileTemplate.indexOf(' if user.instagram'); profileTemplate.splice(index - 1, 5); fs.writeFileSync( 'views/account/profile.jade', profileTemplate.join(os.EOL) ); index = app.indexOf( 'app.get("/auth/instagram", passport.authenticate("instagram"));' ); app.splice(index, 4); fs.writeFileSync('app.js', app.join(os.EOL)); userModel.splice(index, 1); fs.writeFileSync('models/User.js', userModel.join(os.EOL)); } home.remove(authForm); home.append(success); success.setContent( 'Selected authentication providers have been removed' + 'from passportConfig.js, User.js, app.js, login.jade and profile.jade!' ); success.focus(); screen.render(); }); var authText = blessed.text({ parent: authForm, content: 'Selecting a checkbox removes an authentication provider.' + ' If authentication provider is already removed, no action will be taken.', padding: 1, bg: 'magenta', fg: 'white' }); var facebookCheckbox = blessed.checkbox({ parent: authForm, top: 6, mouse: true, fg: 'white', bg: 'blue', content: 'Facebook' }); var githubCheckbox = blessed.checkbox({ parent: authForm, top: 7, mouse: true, fg: 'white', bg: 'blue', content: 'GitHub' }); var googleCheckbox = blessed.checkbox({ parent: authForm, top: 8, mouse: true, fg: 'white', bg: 'blue', content: 'Google' }); var twitterCheckbox = blessed.checkbox({ parent: authForm, top: 9, mouse: true, fg: 'white', bg: 'blue', content: 'Twitter' }); var linkedinCheckbox = blessed.checkbox({ parent: authForm, top: 10, mouse: true, fg: 'white', bg: 'blue', content: 'LinkedIn' }); var instagramCheckbox = blessed.checkbox({ parent: authForm, top: 11, mouse: true, fg: 'white', bg: 'blue', content: 'Instagram' }); var authSubmit = blessed.button({ parent: authForm, top: 13, mouse: true, shrink: true, name: 'submit', content: ' SUBMIT ', style: { fg: 'blue', bg: 'white', focus: { fg: 'white', bg: 'red' } } }); authSubmit.on('press', function() { authForm.submit(); }); var authCancel = blessed.button({ parent: authForm, top: 13, left: 9, mouse: true, shrink: true, name: 'cancel', content: ' CANCEL ', style: { fg: 'blue', bg: 'white', focus: { fg: 'white', bg: 'red' } } }); authCancel.on('press', function() { home.focus(); home.remove(authForm); screen.render(); }); var emailForm = blessed.form({ mouse: true, keys: true, fg: 'white', bg: 'blue', padding: { left: 1, right: 1 } }); emailForm.on('submit', function() { var contactCtrl = fs.readFileSync('controllers/contact.js') .toString().split(os.EOL); var userCtrl = fs.readFileSync('controllers/user.js') .toString().split(os.EOL); var choice = null; if (sendgridRadio.checked) { choice = 'SendGrid'; } else if (mailgunRadio.checked) { choice = 'Mailgun'; } else if (mandrillRadio.checked) { choice = 'Mandrill'; } var index = contactCtrl.indexOf( 'var transporter = nodemailer.createTransport({' ); contactCtrl.splice(index + 1, 1, " service: '" + choice + "',"); contactCtrl.splice( index + 3, 1, ' user: secrets.' + choice.toLowerCase() + '.user,' ); contactCtrl.splice( index + 4, 1, ' pass: secrets.' + choice.toLowerCase() + '.password' ); fs.writeFileSync('controllers/contact.js', contactCtrl.join(os.EOL)); index = userCtrl.indexOf( ' var transporter = nodemailer.createTransport({' ); userCtrl.splice(index + 1, 1, " service: '" + choice + "',"); userCtrl.splice( index + 3, 1, ' user: secrets.' + choice.toLowerCase() + '.user,' ); userCtrl.splice( index + 4, 1, ' pass: secrets.' + choice.toLowerCase() + '.password' ); index = userCtrl.indexOf( ' var transporter = nodemailer.createTransport({', (index + 1) ); userCtrl.splice( index + 1, 1, ' service: "' + choice + '",' ); userCtrl.splice( index + 3, 1, ' user: secrets.' + choice.toLowerCase() + '.user,' ); userCtrl.splice( index + 4, 1, ' pass: secrets.' + choice.toLowerCase() + '.password' ); fs.writeFileSync('controllers/user.js', userCtrl.join(os.EOL)); home.remove(emailForm); home.append(success); success.setContent('Email Service has been switched to ' + choice); success.focus(); screen.render(); }); var emailText = blessed.text({ parent: emailForm, content: 'Select one of the following email service providers ' + 'for {underline}contact form{/underline}' + ' and {underline}password reset{/underline}.', padding: 1, bg: 'red', fg: 'white', tags: true }); var sendgridRadio = blessed.radiobutton({ parent: emailForm, top: 5, checked: true, mouse: true, fg: 'white', bg: 'blue', content: 'SendGrid' }); var mailgunRadio = blessed.radiobutton({ parent: emailForm, top: 6, mouse: true, fg: 'white', bg: 'blue', content: 'Mailgun' }); var mandrillRadio = blessed.radiobutton({ parent: emailForm, top: 7, mouse: true, fg: 'white', bg: 'blue', content: 'Mandrill' }); var emailSubmit = blessed.button({ parent: emailForm, top: 9, mouse: true, shrink: true, name: 'submit', content: ' SUBMIT ', style: { fg: 'blue', bg: 'white', focus: { fg: 'white', bg: 'red' } } }); emailSubmit.on('press', function() { emailForm.submit(); }); var emailCancel = blessed.button({ parent: emailForm, top: 9, left: 9, mouse: true, shrink: true, name: 'cancel', content: ' CANCEL ', style: { fg: 'blue', bg: 'white', focus: { fg: 'white', bg: 'red' } } }); emailCancel.on('press', function() { home.focus(); home.remove(emailForm); screen.render(); }); home.on('select', function(child, index) { switch (index) { case 0: home.append(authForm); authForm.focus(); screen.render(); break; case 1: home.append(emailForm); emailForm.focus(); break; case 2: addClusterSupport(); home.append(success); success.setContent([ 'New file {underline}cluster_app.js{/underline} has been created.', 'Your app is now able to use more than 1 CPU by running', '{underline}node cluster_app.js{/underline}, which in turn', 'spawns multiple instances of {underline}app.js{/underline}' ].join(' ')); success.focus(); screen.render(); break; default: process.exit(0); } }); screen.render(); function addClusterSupport() { var fileContents = multiline(function() { /* var os = require('os'); var cluster = require('cluster'); cluster.setupMaster({ exec: 'app.js' }); cluster.on('exit', function(worker) { console.log('worker ' + worker.id + ' died'); cluster.fork(); }); for (var i = 0; i < os.cpus().length; i++) { cluster.fork(); } */ }); fs.writeFileSync('cluster_app.js', fileContents); }