UNPKG

@ionic/cli-utils

Version:
172 lines (171 loc) 8.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const cli_framework_1 = require("@ionic/cli-framework"); const process_1 = require("@ionic/cli-framework/utils/process"); const shell_1 = require("@ionic/cli-framework/utils/shell"); const streams_1 = require("@ionic/cli-framework/utils/streams"); const chalk_1 = require("chalk"); const Debug = require("debug"); const path = require("path"); const split2 = require("split2"); const guards_1 = require("../guards"); const errors_1 = require("./errors"); const debug = Debug('ionic:cli-utils:lib:shell'); class Shell { constructor(e, options) { this.e = e; this.alterPath = options && options.alterPath ? options.alterPath : (p) => p; } run(command, args, _a) { var { stream, killOnExit = true, showCommand = true, showError = true, fatalOnNotFound = true, fatalOnError = true, truncateErrorOutput } = _a, crossSpawnOptions = tslib_1.__rest(_a, ["stream", "killOnExit", "showCommand", "showError", "fatalOnNotFound", "fatalOnError", "truncateErrorOutput"]); return tslib_1.__awaiter(this, void 0, void 0, function* () { this.prepareSpawnOptions(crossSpawnOptions); const cmd = new shell_1.ShellCommand(command, args, crossSpawnOptions); const fullCmd = cmd.bashify(); const truncatedCmd = fullCmd.length > 80 ? fullCmd.substring(0, 80) + '...' : fullCmd; if (showCommand && this.e.log.level >= cli_framework_1.LOGGER_LEVELS.INFO) { this.e.log.rawmsg(`> ${chalk_1.default.green(fullCmd)}`); } const ws = stream ? stream : this.e.log.createWriteStream(cli_framework_1.LOGGER_LEVELS.INFO, false); try { const promise = cmd.run(); if (promise.p.stdout) { const s = streams_1.combineStreams(split2(), ws); // TODO: https://github.com/angular/angular-cli/issues/10922 s.on('error', (err) => { debug('Error in subprocess stdout pipe: %o', err); }); promise.p.stdout.pipe(s); } if (promise.p.stderr) { const s = streams_1.combineStreams(split2(), ws); // TODO: https://github.com/angular/angular-cli/issues/10922 s.on('error', (err) => { debug('Error in subprocess stderr pipe: %o', err); }); promise.p.stderr.pipe(s); } if (killOnExit) { process_1.onBeforeExit(() => tslib_1.__awaiter(this, void 0, void 0, function* () { if (promise.p.pid) { yield process_1.killProcessTree(promise.p.pid); } })); } yield promise; } catch (e) { if (e instanceof cli_framework_1.ShellCommandError && e.code === cli_framework_1.ERROR_SHELL_COMMAND_NOT_FOUND) { if (fatalOnNotFound) { throw new errors_1.FatalException(`Command not found: ${chalk_1.default.green(command)}`, 127); } else { throw e; } } if (!guards_1.isExitCodeException(e)) { throw e; } let err = e.message || ''; if (truncateErrorOutput && err.length > truncateErrorOutput) { err = `${chalk_1.default.bold('(truncated)')} ... ` + err.substring(err.length - truncateErrorOutput); } const publicErrorMsg = (`An error occurred while running subprocess ${chalk_1.default.green(command)}.\n` + `${chalk_1.default.green(truncatedCmd)} exited with exit code ${e.exitCode}.\n\n` + `Re-running this command with the ${chalk_1.default.green('--verbose')} flag may provide more information.`); const privateErrorMsg = `Subprocess (${chalk_1.default.green(command)}) encountered an error (exit code ${e.exitCode}).`; if (fatalOnError) { if (showError) { throw new errors_1.FatalException(publicErrorMsg, e.exitCode); } else { throw new errors_1.FatalException(privateErrorMsg, e.exitCode); } } else { if (showError) { this.e.log.error(publicErrorMsg); } } throw e; } }); } output(command, args, _a) { var { fatalOnNotFound = true, fatalOnError = true, showError = true, showCommand = false } = _a, crossSpawnOptions = tslib_1.__rest(_a, ["fatalOnNotFound", "fatalOnError", "showError", "showCommand"]); return tslib_1.__awaiter(this, void 0, void 0, function* () { const cmd = new shell_1.ShellCommand(command, args, crossSpawnOptions); const fullCmd = cmd.bashify(); const truncatedCmd = fullCmd.length > 80 ? fullCmd.substring(0, 80) + '...' : fullCmd; if (showCommand && this.e.log.level >= cli_framework_1.LOGGER_LEVELS.INFO) { this.e.log.rawmsg(`> ${chalk_1.default.green(fullCmd)}`); } try { return yield cmd.output(); } catch (e) { if (e instanceof cli_framework_1.ShellCommandError && e.code === cli_framework_1.ERROR_SHELL_COMMAND_NOT_FOUND) { if (fatalOnNotFound) { throw new errors_1.FatalException(`Command not found: ${chalk_1.default.green(command)}`, 127); } else { throw e; } } if (!guards_1.isExitCodeException(e)) { throw e; } const errorMsg = `An error occurred while running ${chalk_1.default.green(truncatedCmd)} (exit code ${e.exitCode})\n`; if (fatalOnError) { throw new errors_1.FatalException(errorMsg, e.exitCode); } else { if (showError) { this.e.log.error(errorMsg); } } return ''; } }); } spawn(command, args, _a) { var { showCommand = true } = _a, crossSpawnOptions = tslib_1.__rest(_a, ["showCommand"]); this.prepareSpawnOptions(crossSpawnOptions); const cmd = new shell_1.ShellCommand(command, args, crossSpawnOptions); const p = cmd.spawn(); if (showCommand && this.e.log.level >= cli_framework_1.LOGGER_LEVELS.INFO) { this.e.log.rawmsg(`> ${chalk_1.default.green(cmd.bashify())}`); } return p; } cmdinfo(command, args = []) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const opts = {}; this.prepareSpawnOptions(opts); const cmd = new shell_1.ShellCommand(command, args, opts); try { const out = yield cmd.output(); return out.split('\n').join(' ').trim(); } catch (e) { // no command info at this point } }); } prepareSpawnOptions(options) { // Create a `process.env`-type object from all key/values of `process.env`, // then `options.env`, then add several key/values. PATH is supplemented // with the `node_modules\.bin` folder in the project directory so that we // can run binaries inside a project. options.env = process_1.createProcessEnv(process.env, options.env, { PATH: this.alterPath(process.env.PATH || ''), FORCE_COLOR: chalk_1.default.enabled ? '1' : '0', }); } } exports.Shell = Shell; function prependNodeModulesBinToPath(projectDir, p) { return path.resolve(projectDir, 'node_modules', '.bin') + path.delimiter + p; } exports.prependNodeModulesBinToPath = prependNodeModulesBinToPath;