UNPKG

@titanium/appcelerator

Version:

⭐ Axway Amplify command-line (CLI) tool for installing Appcelerator Titanium SDK

142 lines (125 loc) 5 kB
/** * This code is closed source and Confidential and Proprietary to * Appcelerator, Inc. All Rights Reserved. This code MUST not be * modified, copied or otherwise redistributed without express * written permission of Appcelerator. This file is licensed as * part of the Appcelerator Platform and governed under the terms * of the Appcelerator license agreement. */ var debug = require('debug')('appc:run'); /** * run the real appc binary by setting up the correct environment location * and then delegate directly (via a spawn) to the real appc binary in our package * @param {string} installBin - Installation binary to run * @param {string[]} additionalArgs - Array of additional args to pass along * @param {function} cb - Function to call when complete * @param {boolean} dontexit - Do not exit after process has finished */ function run(installBin, additionalArgs, cb, dontexit) { var async = require('async'), chalk = require('chalk'), spawn = require('child_process').spawn, // eslint-disable-line security/detect-child-process path = require('path'), fs = require('fs'), util = require('./util'), isWin = /^win/.test(process.platform); // append any incoming program args var args = [ installBin ].concat(process.argv.splice(2)); // add any additional args if (additionalArgs) { args = args.concat(additionalArgs); } // get the environment var env = process.env; // setup our node environment by first appending our appc node_modules env.NODE_PATH = path.resolve(path.join(path.dirname(installBin), '..', 'node_modules')) + path.delimiter // and then our global cache directory + path.join(util.getCacheDir(), 'node_modules') + path.delimiter // then pickup any paths already setup in our env + (env.NODE_PATH || ''); debug('run with env=%j, args=%o', env, args); async.series([ function (next) { var packageDir = path.join(installBin, '..', '..'), isJSON = args.indexOf('json') !== -1, rebuildOpts = { stdio: 'ignore', cwd: packageDir }, child; debug('run check package modules version'); if (installBin && util.isModuleVersionChanged(installBin)) { util.outputInfo(chalk.yellow('\nYou are attempting to run appc ' + util.getActiveVersion() + ' which was compiled for node ' + util.getPackageNodeVersion(installBin) + ' but you are now running node ' + process.version + '\n'), isJSON); util.outputInfo(chalk.yellow('Rebuilding package modules ...\n'), isJSON); debug('exec: npm rebuild in dir %s', packageDir); if (/^win/.test(process.platform)) { child = spawn(process.env.comspec, [ '/c', 'npm' ].concat([ 'rebuild' ]), rebuildOpts); } else { child = spawn('npm', [ 'rebuild' ], rebuildOpts); } child.on('exit', function (exit) { if (exit === 0) { // update node version util.writeVersions(path.join(packageDir, '..')); util.outputInfo(chalk.yellow('Package modules rebuilt!\n'), isJSON); } else { util.outputInfo(chalk.yellow('The rebuild was unsuccessful, please run the following command to re-build for the newer version:\n'), isJSON); util.outputInfo(chalk.green('appc use ' + util.getActiveVersion() + ' --force\n'), isJSON); } next(); }); } else { next(); } }, function (next) { // check that this version of the cli supports the currently selected node version const packageJsonLocation = path.join(installBin, '..', '..', 'package.json'); if (!fs.existsSync(packageJsonLocation)) { next(); } try { const packageJson = require(packageJsonLocation); if (!packageJson.engines || !packageJson.engines.node) { return next(); } util.checkNodeVersion(packageJson.engines.node); } catch (e) { /* squash */ } next(); }, function (next) { // create our child process which simply inherits this process stdio var child = spawn(process.execPath, args, { env: env, stdio: 'inherit' }); // on exit of child, exit ourselves with same exit code child.on('close', function (code) { next(null, code); }); // propagate signals to child process [ 'SIGTERM', 'SIGUSR1', 'SIGUSR2', 'SIGINT', 'SIGHUP', 'SIGQUIT', 'SIGABRT', 'exit' ].forEach(function (name) { process.on(name, function (code) { // Windows does not support sending signals if (!isWin) { // Wait until the child could safely handle it's own cleanup and prevent the main // process to remain alive, mainly because the child wasn't able to leave on time debug('signal received', name, 'code:', code, ', sending to', child); if (name === 'exit') { child.kill(); process.exit(Array.isArray(code) ? code[code.length - 1] : code); } else { child.kill(name); } } }); }); } ], function (error, results) { if (cb) { cb(results); } if (!dontexit) { process.exit(Array.isArray(results) ? results[results.length - 1] : results); } }); } module.exports = run;