UNPKG

divshot-cli

Version:
214 lines (190 loc) 7.05 kB
var chalk = require('chalk'); var _ = require('lodash'); var path = require('path'); var fs = require('fs'); var promptly = require('promptly'); var async = require('async'); var divshot2Firebase = function(source) { var warnings = []; var actions = []; var out = {}; var data = {}; var track = {}; out.firebase = source.name; out.public = source.root || "."; if (source.exclude) { out.ignore = source.exclude; } else { out.ignore = ["firebase.json","**/.*","**/node_modules/**"] } if (source.clean_urls) { warnings.push(chalk.bold("clean_urls") + " support is planned for Firebase Hosting, but is not yet available"); track.clean_urls = true; } if (source.error_page && source.error_page !== '404.html') actions.push("Rename " + chalk.bold(source.error_page) + " to " + chalk.bold("404.html")); if (source.proxy) { warnings.push("Firebase Hosting does not support AJAX proxying"); track.ajax_proxy = true; } if (source.forms) { warnings.push("Firebase Hosting does not support form-to-email"); track.forms = true; } if (source.prerender) { warnings.push("Firebase Hosting does not presently support JS prerendering"); track.prerender = true; } if (fs.existsSync('.env.json')) { warnings.push("Firebase Hosting does not support JS environment variables"); track.env = true; } if (_.isObject(source.routes)) { source.routes = [source.routes]; } _.forEach(source.routes || [], function(routeObject) { _.forEach(routeObject, function(val, key) { out.rewrites = out.rewrites || []; out.rewrites.push({ source: key, destination: path.normalize('/' + val) }); }); }); if (_.isObject(source.redirects)) { source.redirects = [source.redirects]; } _.forEach(source.redirects || [], function(redirectObject) { _.forEach(redirectObject, function(val, key) { out.redirects = out.redirects || []; if (_.isString(val)) { var obj = { source: key, destination: val, type: 301 }; } else { var obj = { source: key, destination: val.url, type: val.status } } if (_.contains(key, ':')) { warnings.push('Redirect for ' + chalk.bold(key) + ' contains path segments. This is not yet supported by Firebase Hosting.'); track.redirect_segments = true; } out.redirects.push(obj); }); }); _.forEach(source.headers || {}, function(val, key) { var obj = {source: key, headers: []}; _.forEach(val || {}, function(headerVal, headerKey) { if (_.contains([ 'Cache-Control', 'Access-Control-Allow-Origin', 'X-UA-Compatible', 'X-Content-Type-Options', 'X-Frame-Options', 'X-XSS-Protection' ])) { obj.headers.push({key: headerKey, value: headerVal}); } else { warnings.push('The ' + chalk.bold(headerKey) + ' header is not allowed by Firebase Hosting.'); track.invalid_header = true; } }); out.headers = out.headers || []; out.headers.push(obj); }); _.forEach(source.cache_control || {}, function(val, key) { out.headers = out.headers || []; var outVal; if (_.isNumber(val)) { outVal = 'public, max-age=' + val.toString(); } else if (_.isString(val)) { outVal = val; } if (outVal) { out.headers.push({ source: key, headers: [{key: 'Cache-Control', value: outVal}] }); } }); return { warnings: warnings, actions: actions, track: track, output: out } } module.exports = function (cli) { cli.command('migrate') .description('migrate a Divshot app to Firebase Hosting') .handler(function (done) { var divshotConfigPath = path.resolve('divshot.json'); var firebaseConfigPath = path.resolve('firebase.json'); if (!fs.existsSync(divshotConfigPath)) { return done("Couldn't find divshot.json. Please run in a Divshot app dierctory."); } if (fs.existsSync(firebaseConfigPath)) { return done("Can't proceed, there is already a firebase.json in this directory."); } var source = require(divshotConfigPath); var result = divshot2Firebase(source); console.log(); console.log(chalk.underline('Migrating Divshot app ' + chalk.bold(source.name) + ' to Firebase Hosting')); console.log(); async.series({ firebase: function(callback) { promptly.prompt('What is your Firebase project\'s name? (' + result.output.firebase + ') ', { default: result.output.firebase, }, callback) }, track: function(callback) { promptly.confirm('Can we anonymously report which features your app used (for Firebase Hosting roadmap planning, etc.)? (y/n)', callback); }, write: function(callback) { promptly.confirm('Write firebase.json? (y/n)', callback); } }, function(err, inputs) { var warningSign = process.platform === 'win32' ? '!' : '⚠'; if (result.warnings.length) { console.log(); console.log(chalk.yellow.bold.underline(warningSign + ' Warning: The following incompatible features were detected.')); _.forEach(result.warnings, function(warning) { console.log('- ' + warning); }); console.log(); console.log(' ' + chalk.bold("Don't panic!"), "Some features may be coming soon or there may be workarounds.\n Contact", chalk.bold.underline("support@firebase.com"), "with any questions."); } if (result.actions.length) { console.log(); console.log(chalk.cyan.bold.underline('You need to take the following actions to fully migrate your app:')); _.forEach(result.actions, function(action) { console.log('- ' + action); }); } result.output.firebase = inputs.firebase; if (inputs.write) { fs.writeFileSync(firebaseConfigPath, JSON.stringify(result.output, null, 2), 'utf-8'); console.log(); console.log(chalk.green('Wrote firebase.json configuration file.')); } console.log(); console.log('If you have the latest version of ' + chalk.bold('firebase-tools') + ' you should now be able'); console.log('to run ' + chalk.bold('firebase serve') + ' in this directory to start a local server and'); console.log(chalk.bold('firebase deploy') + ' to deploy to Firebase Hosting.'); console.log(); console.log('See ' + chalk.bold.underline('http://docs.divshot.com/migrate') + ' for additional migration info.'); console.log(); if (inputs.track) { var mixpanel = require('mixpanel').init('df1a3bd1b07c3caa45a6ea4fd0f163f1'); mixpanel.track('Firebase Migration', result.track, function(err) { done(); }); } else { done(); } }); }); };