TOTVSTEC/cloudbridge-cli

View on GitHub
src/tasks/cordova/start.js

Summary

Maintainability
F
6 days
Test Coverage
'use strict';

var path = require('path'),
    fs = require('fs'),
    shelljs = require('shelljs'),
    Q = require('q'),
    inquirer = require('inquirer'),
    TaskBase = require('./../task-base'),
    Package = cb_require('utils/package'),
    cordova = cb_require('utils/cordova'),
    CloudBridgeProject = cb_require('project/project');

var utils = cli.utils,
    logging = cli.logging;


class StartTask extends TaskBase {

    run(cloudbridge, argv) {

        if (argv._.length < 2) {
            return utils.fail('Invalid command', 'start');
        }

        if (argv._[1] == '.') {
            console.log('Please name your CloudBridge project something more meaningful than \'.\''.red);
            return;
        }

        var promptPromise,
            options = utils.preprocessCliOptions(argv),
            startingApp = true;

        options.targetPath = path.join(this.projectDir, options.appDirectory);

        if (fs.existsSync(options.targetPath)) {
            var _argv = require('optimist').boolean(['list']).argv;

            promptPromise = StartTask.promptForOverwrite(options.targetPath, _argv);
        }
        else {
            promptPromise = Q(true);
        }

        return promptPromise
            .then(function(promptToContinue) {
                if (!promptToContinue) {
                    startingApp = false;
                    console.log('\nCloudBridge start cancelled by user.\n'.red.bold);
                    return;
                }
                return StartTask.startApp(options);
            })
            .then(function() {
                if (startingApp) {
                    StartTask.printQuickHelp(options);
                }
            })
            .catch(function(error) {
                utils.fail(error);
            });


    }

    static promptForOverwrite(targetPath, _argv) {
        var deferred = Q.defer(),
            choiceOverwrite = {
                name: 'Overwrite',
                value: 0,
                short: '\nOverwriting the existing files...'
            },
            choiceRename = {
                name: 'Rename',
                value: 1,
                short: '\nRenaming the existing directory and copying the new files...'
            };

        inquirer.prompt([{
            type: 'list',
            name: 'action',
            message: ['The directory'.error.bold, targetPath, 'already exists.\n'.error.bold].join(' '),
            choices: [choiceOverwrite, choiceRename],
            default: choiceRename.value
        }]).then(function(answers) {
            if (answers.action === choiceRename.value) {
                var renamedPath = targetPath + '.old';

                if (fs.existsSync(renamedPath)) {
                    var count = 1;
                    while (fs.existsSync(renamedPath + '.' + count)) {
                        count++;
                    }

                    renamedPath += '.' + count;
                }

                shelljs.mv(targetPath, renamedPath);
            }
            else if (answers.action === choiceOverwrite.value) {
                shelljs.rm('-rf', targetPath);
            }

            deferred.resolve(true);
        });

        return deferred.promise;
    }

    static startApp(options) {
        if (typeof options !== 'object' || typeof options === 'undefined') {
            throw new Error('You cannot start an app without options');
        }

        if (typeof options.targetPath == 'undefined' || options.targetPath == '.') {
            throw new Error('Invalid target path, you may not specify \'.\' as an app name');
        }

        //shelljs.mkdir('-p', options.targetPath);

        return Q()
            .then(() => {
                var createMessage = [
                    '\nCreating CloudBridge Cordova-like app in folder',
                    options.targetPath,
                    'based on',
                    options.template.bold,
                    'project\n'
                ].join(' ');

                logging.logger.info(createMessage);

                var args = [
                    options.targetPath,
                    options.packageName,
                    options.appDirectory
                ];

                return cordova.create(...args);
            })
            .then(() => {
                return StartTask.createProjectFile(options);
            })
            .then(function() {
                return StartTask.fetchWrapper(options);
            })
            .then(function() {
                return StartTask.finalize(options);
            })
            .catch(function(err) {
                logging.logger.error('Error Initializing app: %s', err, {});

                throw err;
            });
    }

    static printQuickHelp(options) {
        logging.logger.info('\n\nYour CloudBridge Cordova-like app is ready to go!'.bold);
        logging.logger.info('\n\nMake sure to cd into your new app directory:'.bold);
        logging.logger.info('  cd ' + options.appName);
        logging.logger.info('\nAdd some platforms:'.bold);
        logging.logger.info('  cloudbridge platform add android ios');
        logging.logger.info('\nTo build on android:'.bold);
        logging.logger.info('  cloudbridge build android');
        logging.logger.info('\nTo run on android:'.bold);
        logging.logger.info('  cloudbridge run android');
    }

    static fetchWrapper(options) {
        var pack = new Package('cloudbridge-core-cordova');

        return Q()
            .then(function() {
                return pack.latest();
            })
            .then(function() {
                options.version = pack.version;

                var project = CloudBridgeProject.load(options.targetPath),
                    components = project.get('components') || {};

                components.advpl = components.advpl || {};
                components.advpl[pack.name] = '^' + pack.version;

                project.set('components', components);
                project.save();

                return pack.fetch();
            })
            .then(function() {
                var deferred = Q.defer();
                var projectData = require(path.join(options.targetPath, 'cloudbridge.json'));

                pack.install(options.targetPath, projectData)
                    .then(function() {
                        deferred.resolve();
                    })
                    .catch(function() {
                        shelljs.cp('-Rf', path.join(pack.src, pack.version, 'src'), options.targetPath);
                        shelljs.cp('-Rf', path.join(pack.src, pack.version, 'build'), options.targetPath);
                        shelljs.cp('-Rf', path.join(pack.src, pack.version, 'plugins'), options.targetPath);
                        shelljs.cp('-Rf', path.join(pack.src, pack.version, 'www'), options.targetPath);

                        shelljs.cd(options.targetPath);

                        deferred.resolve();
                    });

                return deferred.promise;
            });

    }

    static finalize(options) {
        try {
            // update the app name in the bower.json file
            var cloudbridgeBower = require('./bower').CloudBridgeBower;
            cloudbridgeBower.setAppName(options.appName);
        }
        catch (e) { }

        try {
            // remove the README file in the root because it
            // doesn't make sense because its the README for the repo
            // and not helper text while developing an app
            fs.unlinkSync(options.targetPath + '/README.md');
        }
        catch (e) { }
    }

    static createProjectFile(options) {
        try {
            // create the cloudbridge.json file and
            // set the app name
            var project = CloudBridgeProject.create(options.targetPath, options.appName);
            project.set('name', options.appName);

            if (options.packageName) {
                project.set('id', options.packageName);
            }

            project.set('engine', 'cordova');

            project.save(options.targetPath);
        }
        catch (e) {
            console.error('Error saving project file');
        }

        return Q();
    }

}

module.exports = StartTask;