From 51d2dba505c212288788f19e2e69f3ffffa477a0 Mon Sep 17 00:00:00 2001 From: Rob DiMarco Date: Mon, 12 May 2014 11:53:15 -0700 Subject: [PATCH] Remove hard-coded templates, store in firebase-public, update help, handle offline use --- lib/app.js | 83 ++++++++++++++++++++++++----------------------------- lib/help.js | 44 +++++++++++++++++++--------- 2 files changed, 68 insertions(+), 59 deletions(-) diff --git a/lib/app.js b/lib/app.js index 0a4e00ba37b..d8f6584d516 100644 --- a/lib/app.js +++ b/lib/app.js @@ -13,44 +13,8 @@ var request = require('request'), auth = require('./auth'), api = require('./api'), util = require('util'), - chalk = require('chalk'); - -var supportedTemplates = { - angular: { - url: 'https://codeload.github.com/firebase/angularFire-seed/legacy.tar.gz/master', - settings: { - 'public': 'app', - 'rules': 'config/security-rules.json', - }, - config: 'app/js/config.js', - configRegex: /https:\/\/INSTANCE\.firebaseio\.com/, - onComplete: function(results) { - this._onComplete('chat template', results); - } - }, - chat: { - url: 'https://codeload.github.com/firebase/chat-seed/legacy.tar.gz/master', - settings: { - 'public': 'public', - 'rules': 'config/rules.json', - }, - config: 'public/index.html', - configRegex: /https:\/\/INSTANCE\.firebaseio\.com/, - onComplete: function(results) { - this._onComplete('chat template', results); - } - }, - _onComplete: function(type, results) { - console.log(chalk.green('Successfully added template')); - console.log('To deploy: %s then %s', chalk.bold(util.format('cd %s/', results.directory)), chalk.bold('firebase deploy')); - //console.log('To deploy this app, run %s', chalk.bold(util.format('cd %s && firebase deploy', results.directory))); - }, - _getTemplates: function() { - return Object.keys(this).filter(function(key) { - return !key.match(/^_/); - }); - } -}; + chalk = require('chalk'), + _when = require('when'); var defaultSettings = { 'public': '.' @@ -183,7 +147,9 @@ module.exports = { }); }, bootstrap: function(argv) { - auth.listFirebases().then(function(res) { + _when.join(this.getTemplates(), auth.listFirebases()).done(function(resultSet) { + var supportedTemplates = resultSet[0], + res = resultSet[1]; if (res.firebases.length === 0) { console.log(chalk.yellow('You have no apps in your Firebase account')); @@ -193,9 +159,9 @@ module.exports = { } // Firebase names always a subset of ^[0-9a-z-]*$ so safe to regex + var templateList = Object.keys(supportedTemplates); var firebasePattern = new RegExp('^(' + res.firebases.join('|') + ')$'); - var templatePattern = new RegExp('^(' + - supportedTemplates._getTemplates().join('|') + ')$'); + var templatePattern = new RegExp('^(' + templateList.join('|') + ')$'); if (!argv.firebase || (typeof(argv.firebase) !== 'string') || !argv.firebase.match(firebasePattern)) { res.showFirebases(); } @@ -220,7 +186,7 @@ module.exports = { console.log(chalk.yellow('----------------------------------------------------')); console.log(chalk.yellow('Available Templates')); console.log(chalk.yellow('----------------------------------------------------')); - console.log(supportedTemplates._getTemplates().join('\n')); + console.log(templateList.join('\n')); console.log(chalk.yellow('----------------------------------------------------')); console.log('Choose a template to help you get started with your app'); } @@ -272,7 +238,7 @@ module.exports = { var data = fs.readFileSync(config, 'utf8'), realtimeHost = api.realtimeUrl.replace(/\/\//, '//' + firebase + '.'); var replaced = data.replace( - supportedTemplates[results.template].configRegex, + new RegExp(supportedTemplates[results.template].configRegex), realtimeHost ); fs.writeFileSync(config, replaced); @@ -299,9 +265,9 @@ module.exports = { console.log(chalk.red('Filesystem Error') + ' - Could not save settings file'); process.exit(1); } - if (typeof supportedTemplates[results.template].onComplete === 'function') { - supportedTemplates[results.template].onComplete.call(supportedTemplates, results); - } + + console.log(chalk.green('Successfully added template')); + console.log('To deploy: %s then %s', chalk.bold(util.format('cd %s/', results.directory)), chalk.bold('firebase deploy')); }); }); }, function(error) { @@ -310,6 +276,14 @@ module.exports = { console.log(chalk.red('Login Error')); process.exit(1); break; + case 'GET-TEMPLATES': + console.log(chalk.red('Bootstrapping Error: ') + 'Could not retrieve available templates.'); + process.exit(1); + break; + case 'PARSE-TEMPLATES': + console.log(chalk.red('Bootstrapping Error: ') + 'Could not parse available templates.'); + process.exit(1); + break; default: console.log(chalk.red('Bootstrapping Error')); process.exit(1); @@ -460,5 +434,22 @@ module.exports = { process.exit(1); } open(api.hostingUrl.replace(/\/\//, util.format('//%s.', settings.firebase))); + }, + getTemplates: function() { + return _when.promise(function(resolve, reject, notify) { + request('https://firebase-public.firebaseio.com/cli-templates.json', function(error, response, body) { + if (error) { + error.type = 'GET-TEMPLATES'; + return reject(error); + } + + try { + resolve(JSON.parse(body)); + } catch (e) { + error.type = 'PARSE-TEMPLATES'; + return reject(error); + } + }); + }); } }; diff --git a/lib/help.js b/lib/help.js index 272aaa18a90..d9c7df7b902 100644 --- a/lib/help.js +++ b/lib/help.js @@ -1,4 +1,6 @@ -var firebase = require('./firebase'); +var app = require('./app'), + firebase = require('./firebase'), + chalk = require('chalk'); module.exports = { showHelp: function(command) { @@ -67,7 +69,8 @@ module.exports = { ' prompted to do so - see `firebase login --help` for more details.\n'); break; case 'bootstrap': - console.log('\n' + + var helpOverview = + '\n' + ' firebase bootstrap\n' + ' Creates a new Firebase powered app from a prebuilt template to quickly\n' + ' get a project up and running. This creates a new folder and prompts\n' + @@ -78,20 +81,35 @@ module.exports = { ' -f, --firebase The Firebase to initalize the app with. The current user\n' + ' must have access to this Firebase. This is used for the\n' + ' subdomain of firebaseapp.com\n' + - ' -t, --template The name of the template to bootstrap the app with. The\n' + - ' currently available templates are:\n' + - '\n' + - ' angular - https://github.com/firebase/angularFire-seed\n' + - ' The angularFire seed template\n' + - '\n' + - ' chat - https://github.com/firebase/chat-seed\n' + - ' A very simple Firebase powered chat template\n' + - '\n' + + ' -t, --template The name of the template to bootstrap the app with.\n'; + + var helpFooter = '\n' + ' Downloads and unpacks the template into a folder named after the Firebase\n' + ' with which it has been initialized. Creates a firebase.json file in the\n' + ' directory with some pre-configured settings appropriate for the template.\n' + ' If the user is not currently logged in, they are prompted to do so - see\n' + - ' `firebase login --help` for more details.\n'); + ' `firebase login --help` for more details.\n'; + + app.getTemplates() + .done(function(templates) { + var helpTemplates = '\n The currently available templates are:\n'; + for (var key in templates) { + var template = templates[key]; + helpTemplates += '\n ' + key; + helpTemplates += (template.repoUrl) ? ' - ' + template.repoUrl + '\n' : '\n'; + if (template.description) { + helpTemplates += ' ' + template.description; + } + helpTemplates += '\n'; + } + + console.log(helpOverview + helpTemplates + helpFooter); + }, function(error) { + var errTemplates = '\n '; + errTemplates += chalk.red('Error: ') + 'Could not retrieve available templates.\n'; + + console.log(helpOverview + errTemplates + helpFooter); + }); break; case 'deploy': console.log('\n' + @@ -166,4 +184,4 @@ module.exports = { 'Version ' + firebase.version + '\n' + 'https://www.firebase.com\n'); } -} +};