nx
Version:
199 lines (198 loc) • 6.65 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NodeChildProcessWithDirectOutput = exports.NodeChildProcessWithNonDirectOutput = void 0;
const exit_codes_1 = require("../../utils/exit-codes");
const stream_1 = require("stream");
const chalk = require("chalk");
const fs_1 = require("fs");
class NodeChildProcessWithNonDirectOutput {
constructor(childProcess, { streamOutput, prefix }) {
this.childProcess = childProcess;
this.terminalOutput = '';
this.exitCallbacks = [];
this.outputCallbacks = [];
if (streamOutput) {
if (process.env.NX_PREFIX_OUTPUT === 'true') {
const color = getColor(prefix);
const prefixText = `${prefix}:`;
this.childProcess.stdout
.pipe(logClearLineToPrefixTransformer(color.bold(prefixText) + ' '))
.pipe(addPrefixTransformer(color.bold(prefixText)))
.pipe(process.stdout);
this.childProcess.stderr
.pipe(logClearLineToPrefixTransformer(color(prefixText) + ' '))
.pipe(addPrefixTransformer(color(prefixText)))
.pipe(process.stderr);
}
else {
this.childProcess.stdout
.pipe(addPrefixTransformer())
.pipe(process.stdout);
this.childProcess.stderr
.pipe(addPrefixTransformer())
.pipe(process.stderr);
}
}
this.childProcess.on('exit', (code, signal) => {
if (code === null)
code = (0, exit_codes_1.signalToCode)(signal);
this.exitCode = code;
for (const cb of this.exitCallbacks) {
cb(code, this.terminalOutput);
}
});
// Re-emit any messages from the task process
this.childProcess.on('message', (message) => {
if (process.send) {
process.send(message);
}
});
this.childProcess.stdout.on('data', (chunk) => {
const output = chunk.toString();
this.terminalOutput += output;
// Stream output to TUI via callbacks
for (const cb of this.outputCallbacks) {
cb(output);
}
});
this.childProcess.stderr.on('data', (chunk) => {
const output = chunk.toString();
this.terminalOutput += output;
// Stream output to TUI via callbacks
for (const cb of this.outputCallbacks) {
cb(output);
}
});
}
onExit(cb) {
this.exitCallbacks.push(cb);
}
onOutput(cb) {
this.outputCallbacks.push(cb);
}
async getResults() {
if (typeof this.exitCode === 'number') {
return {
code: this.exitCode,
terminalOutput: this.terminalOutput,
};
}
return new Promise((res) => {
this.onExit((code, terminalOutput) => {
res({ code, terminalOutput });
});
});
}
send(message) {
if (this.childProcess.connected) {
this.childProcess.send(message);
}
}
kill(signal) {
if (this.childProcess.connected) {
this.childProcess.kill(signal);
}
}
}
exports.NodeChildProcessWithNonDirectOutput = NodeChildProcessWithNonDirectOutput;
function addPrefixTransformer(prefix) {
const newLineSeparator = process.platform.startsWith('win') ? '\r\n' : '\n';
return new stream_1.Transform({
transform(chunk, _encoding, callback) {
const list = chunk.toString().split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/g);
list
.filter(Boolean)
.forEach((m) => this.push(prefix ? prefix + ' ' + m + newLineSeparator : m + newLineSeparator));
callback();
},
});
}
const colors = [
chalk.green,
chalk.greenBright,
chalk.blue,
chalk.blueBright,
chalk.cyan,
chalk.cyanBright,
chalk.yellow,
chalk.yellowBright,
chalk.magenta,
chalk.magentaBright,
];
function getColor(projectName) {
let code = 0;
for (let i = 0; i < projectName.length; ++i) {
code += projectName.charCodeAt(i);
}
const colorIndex = code % colors.length;
return colors[colorIndex];
}
/**
* Prevents terminal escape sequence from clearing line prefix.
*/
function logClearLineToPrefixTransformer(prefix) {
let prevChunk = null;
return new stream_1.Transform({
transform(chunk, _encoding, callback) {
if (prevChunk && prevChunk.toString() === '\x1b[2K') {
chunk = chunk.toString().replace(/\x1b\[1G/g, (m) => m + prefix);
}
this.push(chunk);
prevChunk = chunk;
callback();
},
});
}
class NodeChildProcessWithDirectOutput {
constructor(childProcess, temporaryOutputPath) {
this.childProcess = childProcess;
this.temporaryOutputPath = temporaryOutputPath;
this.exitCallbacks = [];
this.exited = false;
// Re-emit any messages from the task process
this.childProcess.on('message', (message) => {
if (process.send) {
process.send(message);
}
});
this.childProcess.on('exit', (code, signal) => {
if (code === null)
code = (0, exit_codes_1.signalToCode)(signal);
this.exited = true;
this.exitCode = code;
for (const cb of this.exitCallbacks) {
cb(code, signal);
}
});
}
send(message) {
if (this.childProcess.connected) {
this.childProcess.send(message);
}
}
onExit(cb) {
this.exitCallbacks.push(cb);
}
async getResults() {
if (!this.exited) {
await this.waitForExit();
}
const terminalOutput = this.getTerminalOutput();
return { code: this.exitCode, terminalOutput };
}
waitForExit() {
return new Promise((res) => {
this.onExit(() => res());
});
}
getTerminalOutput() {
this.terminalOutput ??= (0, fs_1.readFileSync)(this.temporaryOutputPath).toString();
return this.terminalOutput;
}
kill(signal) {
if (this.childProcess.connected) {
this.childProcess.kill(signal);
}
}
}
exports.NodeChildProcessWithDirectOutput = NodeChildProcessWithDirectOutput;