CleverStack/cleverstack-cli

View on GitHub
lib/project.js

Summary

Maintainability
D
1 day
Test Coverage
var Promise  = require('bluebird')
  , path     = require('path')
  , async    = require('async')
  , spawn    = require('child_process').spawn
  , readline = require('readline')
  , fs       = Promise.promisifyAll(require('fs'))
  , install  = GLOBAL.lib.install
  , _bower   = GLOBAL.lib.util.bower
  , utils    = GLOBAL.lib.utils
  , os       = require('os')
  , isWin    = /^win32/.test(os.platform());

Promise.longStackTraces();

/**
 * Helper function for running clever-install if there are modules to install
 *
 * @param  {Object} projectFolder location returned by util.locations.get()
 * @param  {String[]} modules
 * @return {Promise}
 * @api public
 */

exports.setupModules = function(projectFolder, modules) {
  return new Promise(function(resolve, reject) {
    var cwd = process.cwd();

    process.chdir(projectFolder.moduleDir);

    install
      .run(modules)
      .then(function() {
        process.chdir(cwd);
        resolve();
      }, function(err) {
        process.chdir(cwd);
        reject(err);
      });
  });
};

/**
 * Installs module bower components within the frontend seed's component dir
 *
 * @param  {Object} projectFolder Object returned from util.locations.get()
 * @return {Promise}              Promise from bluebird
 * @api public
 */

exports.installBowerComponents = function(projectFolder) {
  return new Promise(function(resolve, reject) {
    var bowerRC     = path.join(projectFolder.moduleDir, '.bowerrc')
      , _bowerRC    = fs.readFileSync(bowerRC);

    _bowerRC = JSON.parse(_bowerRC);

    if (program.verbose) {
      utils.info('  Installing bower components for ' + projectFolder.moduleDir + '...');
    }

    _bower.install(projectFolder.moduleDir, function (err) {
      if (!!err) {
        return reject(err);
      }

      async.filter(
        fs.readdirSync(path.join(projectFolder.moduleDir, projectFolder.modulePath)),
        function(dir, next) {
          fs.exists(path.join(projectFolder.moduleDir, projectFolder.modulePath, dir, 'bower.json'), next);
        },
        function (modules, err) {
          if (!!err) {
            return reject(err);
          }

          if (modules.length < 1) {
            return resolve();
          }

          async.each(
            modules,
            function(moduleDir, callback) {
              utils.running('Installing bower components for ' + moduleDir + '...' );
              if (program.verbose) {
                utils.info('  Installing bower components for ' + moduleDir + '...');
              } else {
                utils.info('  Installing bower components for ' + moduleDir.split('/').pop() + '...');
              }

              _bower.install(
                path.join(projectFolder.moduleDir, projectFolder.modulePath, moduleDir),
                {
                  cwd: path.join(projectFolder.moduleDir, projectFolder.modulePath, moduleDir),
                  directory: path.relative(path.join(projectFolder.moduleDir, projectFolder.modulePath, moduleDir), [ projectFolder.moduleDir ].concat(_bowerRC.directory.split('/')).join(path.sep)),
                  env: process.env
                },
                function(err) {
                  callback(err);
                }
             );
            },
            function(moduleErr) {
              if (!!moduleErr) {
                return reject(moduleErr);
              }

              resolve();
            }
         );
        }
     );
    });
  });
};

/**
 * Looks into package.json within the seed's module directory
 * and finds each (dev)dependency and installs individually
 * due to use using the --prefix flag for NPM
 *
 * @param  {Object} project
 * @param  {String} modulePath
 * @param  {Object} programOptions program instance sent by commander
 * @return {Promise}
 * @api public
 */

exports.installModule = function(project, modulePath) {
  return new Promise(function(resolve, reject) {
    var projectFolder   = project.moduleDir
      , moduleDir       = path.join(project.moduleDir, project.modulePath)
      , jsonPath        = path.resolve(path.join(modulePath, 'package.json'))
      , deps            = [];

    if (!fs.existsSync(jsonPath)) {
      return resolve();
    }

    var jsonFile = require(jsonPath);

    jsonFile.dependencies    = jsonFile.dependencies     || {};
    jsonFile.devDependencies = jsonFile.devDependencies  || {};

    Object.keys(jsonFile.dependencies).forEach(function(k) {
      deps.push(k + '@' + jsonFile.dependencies[ k ]);
    });

    Object.keys(jsonFile.devDependencies).forEach(function(k) {
      deps.push(k + '@' + jsonFile.devDependencies[ k ]);
    });

    utils.info('  Installing NPM modules for ' + modulePath.split(path.sep).pop() + '...');
    async.waterfall(
      [
        function installNpmDependencies(callback) {
          var opts = {cwd: moduleDir, env: process.env}
            , args = ['install', '--prefix', projectFolder].concat(deps)
            , cmd  = !isWin ? 'npm' : 'npm.cmd';

          if (!program.verbose) {
            args.push('--silent');
          }

          var posixProc = spawn(cmd, args, opts)
            , exitHdlr  = process.kill.bind(process, posixProc)
            , error     = '';

          process.on('SIGTERM', exitHdlr);

          if (!!program.verbose) {
            readline
              .createInterface({
                input    : posixProc.stdout,
                terminal : false
              })
              .on('line', function(line) {
                console.log('      ' + line);
              });
          }

          posixProc.on('error', function(err) {
            error += err;
          });

          posixProc.on('close', function(code) {
            process.removeListener('SIGTERM', exitHdlr);

            if (code !== 0 || !!error) {
              callback(error);
            } else {
              callback(null);
            }
          });
        },

        function installBowerDependencies(callback) {
          if (program.verbose) {
            utils.success('  Finished installing NPM packages for ' + modulePath.split(path.sep).pop() + '...');
          }

          var bowerPath = path.resolve(path.join(projectFolder, 'bower.json'));

          // backend folder?
          if (!fs.existsSync(bowerPath)) {
            utils.success('  Successfully installed ' + modulePath.split(path.sep).pop() + '...');
            return callback(null);
          }

          utils.info('  Installing bower components for ' + modulePath.split(path.sep).pop() + '...');
          _bower.install(modulePath, function(_err) {
            if (!!_err) {
              return callback(_err);
            }

            utils.success('  Successfully installed ' + modulePath.split(path.sep).pop() + '...');
            callback(null);
          });
        }
      ],
      function checkInstallation(err) {
        if (!!err) {
          resolve();
        } else {
          reject(err);
        }
      }
    );
  });
};