UNPKG

nativescript

Version:

Command-line interface for building NativeScript projects

201 lines • 8.36 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ChildProcess = void 0; const child_process = require("child_process"); const path_1 = require("path"); const events_1 = require("events"); const yok_1 = require("./yok"); class ChildProcess extends events_1.EventEmitter { constructor($logger, $errors) { super(); this.$logger = $logger; this.$errors = $errors; } async exec(command, options, execOptions) { return new Promise((resolve, reject) => { const callback = (error, stdout, stderr) => { this.$logger.trace("Exec %s \n stdout: %s \n stderr: %s", command, stdout.toString(), stderr.toString()); if (error) { reject(error); } else { const output = execOptions && execOptions.showStderr ? { stdout, stderr } : stdout; resolve(output); } }; if (options) { child_process.exec(command, options, callback); } else { child_process.exec(command, callback); } }); } async execFile(command, args) { this.$logger.trace("execFile: %s %s", command, this.getArgumentsAsQuotedString(args)); return new Promise((resolve, reject) => { child_process.execFile(command, args, (error, stdout) => { if (error) { reject(error); } else { resolve(stdout); } }); }); } spawn(command, args, options) { var _a; if (command.charAt(0) === ".") { // resolve relative paths to full paths to avoid node Spawn ENOENT errors on some setups. const cwd = (_a = options === null || options === void 0 ? void 0 : options.cwd) !== null && _a !== void 0 ? _a : process.cwd(); command = (0, path_1.resolve)(cwd, command); } this.$logger.trace("spawn: %s %s", command, this.getArgumentsAsQuotedString(args)); return child_process.spawn(command, args, options); } fork(modulePath, args, options) { this.$logger.trace("fork: %s %s", modulePath, this.getArgumentsAsQuotedString(args)); return child_process.fork(modulePath, args, options); } spawnFromEvent(command, args, event, options, spawnFromEventOptions) { // event should be exit or close return new Promise((resolve, reject) => { const childProcess = this.spawn(command, args, options); let isResolved = false; let capturedOut = ""; let capturedErr = ""; let killTimer = null; if (spawnFromEventOptions && spawnFromEventOptions.timeout) { this.$logger.trace(`Setting maximum time for execution of current child process to ${spawnFromEventOptions.timeout}`); killTimer = setTimeout(() => { this.$logger.trace(`Sending SIGTERM to current child process as maximum time for execution ${spawnFromEventOptions.timeout} had passed.`); childProcess.kill("SIGTERM"); }, spawnFromEventOptions.timeout); } if (childProcess.stdout) { childProcess.stdout.on("data", (data) => { if (spawnFromEventOptions && spawnFromEventOptions.emitOptions && spawnFromEventOptions.emitOptions.eventName) { this.emit(spawnFromEventOptions.emitOptions.eventName, { data, pipe: "stdout", }); } capturedOut += data; }); } if (childProcess.stderr) { childProcess.stderr.on("data", (data) => { if (spawnFromEventOptions && spawnFromEventOptions.emitOptions && spawnFromEventOptions.emitOptions.eventName) { this.emit(spawnFromEventOptions.emitOptions.eventName, { data, pipe: "stderr", }); } capturedErr += data; }); } childProcess.on(event, (arg) => { const exitCode = typeof arg === "number" ? arg : arg && arg.code; const result = { stdout: capturedOut, stderr: capturedErr, exitCode: exitCode, }; const clearKillTimer = () => { if (killTimer) { clearTimeout(killTimer); } }; const resolveAction = () => { isResolved = true; resolve(result); clearKillTimer(); }; if (spawnFromEventOptions && spawnFromEventOptions.throwError === false) { if (!isResolved) { this.$logger.trace("Result when throw error is false:"); this.$logger.trace(result); resolveAction(); } } else { if (exitCode === 0) { resolveAction(); } else { let errorMessage = `Command ${command} failed with exit code ${exitCode}`; if (capturedErr) { errorMessage += ` Error output: \n ${capturedErr}`; } if (!isResolved) { isResolved = true; reject(new Error(errorMessage)); clearKillTimer(); } } } }); childProcess.once("error", (err) => { if (!isResolved) { if (spawnFromEventOptions && spawnFromEventOptions.throwError === false) { const result = { stdout: capturedOut, stderr: err.message, exitCode: err.code, }; isResolved = true; resolve(result); } else { isResolved = true; reject(err); } } }); }); } async trySpawnFromCloseEvent(command, args, options, spawnFromEventOptions) { try { const childProcessResult = await this.spawnFromEvent(command, args, "close", options, spawnFromEventOptions); return childProcessResult; } catch (err) { this.$logger.trace(`Error from trySpawnFromCloseEvent method. More info: ${err}`); return Promise.resolve({ stderr: err && err.message ? err.message : err, stdout: null, exitCode: -1, }); } } async tryExecuteApplication(command, args, event, errorMessage, condition) { const childProcess = await this.tryExecuteApplicationCore(command, args, event, errorMessage); if (condition && condition(childProcess)) { this.$errors.fail(errorMessage); } } async tryExecuteApplicationCore(command, args, event, errorMessage) { try { return this.spawnFromEvent(command, args, event, undefined, { throwError: false, }); } catch (e) { const message = e.code === "ENOENT" ? errorMessage : e.message; this.$errors.fail(message); } } getArgumentsAsQuotedString(args) { return (args && args.length && args.map((argument) => `"${argument}"`).join(" ")); } } exports.ChildProcess = ChildProcess; yok_1.injector.register("childProcess", ChildProcess); //# sourceMappingURL=child-process.js.map