UNPKG

nx

Version:

The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.

254 lines (253 loc) 8.35 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.output = void 0; exports.orange = orange; const pc = require("picocolors"); const os_1 = require("os"); const readline = require("readline"); const GH_GROUP_PREFIX = '::group::'; const GH_GROUP_SUFFIX = '::endgroup::'; /** * Custom orange color using ANSI 256-color code 214. * picocolors does not support keyword-based colors like chalk, * so orange is implemented manually. */ function orange(text) { return pc.isColorSupported ? `\x1b[38;5;214m${text}\x1b[39m` : String(text); } /** * Map of color names to picocolors functions, used for dynamic color access. */ const pcColors = { cyan: pc.cyan, red: pc.red, yellow: pc.yellow, green: pc.green, gray: pc.gray, white: pc.white, blue: pc.blue, magenta: pc.magenta, orange, }; class CLIOutput { constructor() { this.cliName = 'NX'; this.formatCommand = (taskId) => `${pc.dim('nx run')} ${taskId}`; /** * Expose some color and other utility functions so that other parts of the codebase that need * more fine-grained control of message bodies are still using a centralized * implementation. */ this.colors = { gray: pc.gray, green: pc.green, red: pc.red, cyan: pc.cyan, white: pc.white, orange, }; this.bold = pc.bold; this.underline = pc.underline; this.dim = pc.dim; } /** * Longer dash character which forms more of a continuous line when place side to side * with itself, unlike the standard dash character */ get VERTICAL_SEPARATOR() { let divider = ''; for (let i = 0; i < process.stdout.columns - 1; i++) { divider += '\u2014'; } return divider; } writeToStdOut(str) { process.stdout.write(str); } overwriteLine(lineText = '') { // this replaces the existing text up to the new line length process.stdout.write(lineText); // clear whatever text might be left to the right of the cursor (happens // when existing text was longer than new one) readline.clearLine(process.stdout, 1); process.stdout.write(os_1.EOL); } writeOutputTitle({ color, title, }) { this.writeToStdOut(`${this.applyNxPrefix(color, title)}${os_1.EOL}`); } writeOptionalOutputBody(bodyLines) { if (!bodyLines) { return; } this.addNewline(); bodyLines.forEach((bodyLine) => this.writeToStdOut(`${bodyLine}${os_1.EOL}`)); } applyNxPrefix(color = 'cyan', text) { const colorFn = pcColors[color] || ((t) => t); const nxPrefix = pc.inverse(pc.bold(colorFn(` ${this.cliName} `))); return `${nxPrefix} ${text}`; } addNewline() { this.writeToStdOut(os_1.EOL); } addVerticalSeparator(color = 'gray') { this.addNewline(); this.addVerticalSeparatorWithoutNewLines(color); this.addNewline(); } addVerticalSeparatorWithoutNewLines(color = 'gray') { this.writeToStdOut(`${this.getVerticalSeparator(color)}${os_1.EOL}`); } getVerticalSeparatorLines(color = 'gray') { return ['', this.getVerticalSeparator(color), '']; } getVerticalSeparator(color) { const colorFn = pcColors[color] || ((t) => t); return pc.dim(colorFn(this.VERTICAL_SEPARATOR)); } error({ title, slug, bodyLines }) { this.addNewline(); this.writeOutputTitle({ color: 'red', title: pc.red(title), }); this.writeOptionalOutputBody(bodyLines); /** * Optional slug to be used in an Nx error message redirect URL */ if (slug && typeof slug === 'string') { this.addNewline(); this.writeToStdOut(`${pc.gray(' Learn more about this error: ')}https://errors.nx.dev/${slug}${os_1.EOL}`); } this.addNewline(); } warn({ title, slug, bodyLines }) { this.addNewline(); this.writeOutputTitle({ color: 'yellow', title: pc.yellow(title), }); this.writeOptionalOutputBody(bodyLines); /** * Optional slug to be used in an Nx warning message redirect URL */ if (slug && typeof slug === 'string') { this.addNewline(); this.writeToStdOut(`${pc.gray(' Learn more about this warning: ')}https://errors.nx.dev/${slug}${os_1.EOL}`); } this.addNewline(); } note({ title, bodyLines }) { this.addNewline(); this.writeOutputTitle({ color: 'orange', title: orange(title), }); this.writeOptionalOutputBody(bodyLines); this.addNewline(); } success({ title, bodyLines }) { this.addNewline(); this.writeOutputTitle({ color: 'green', title: pc.green(title), }); this.writeOptionalOutputBody(bodyLines); this.addNewline(); } logSingleLine(message) { this.addNewline(); this.writeOutputTitle({ color: 'gray', title: message, }); this.addNewline(); } logCommand(message, taskStatus) { this.addNewline(); this.writeToStdOut(this.getCommandWithStatus(message, taskStatus)); this.addNewline(); this.addNewline(); } logCommandOutput(message, taskStatus, output) { let commandOutputWithStatus = this.getCommandWithStatus(message, taskStatus); if (process.env.NX_SKIP_LOG_GROUPING !== 'true' && process.env.GITHUB_ACTIONS) { const icon = this.getStatusIcon(taskStatus); commandOutputWithStatus = `${GH_GROUP_PREFIX}${icon} ${commandOutputWithStatus}`; } this.addNewline(); this.writeToStdOut(commandOutputWithStatus); this.addNewline(); this.addNewline(); this.writeToStdOut(output); if (process.env.NX_SKIP_LOG_GROUPING !== 'true' && process.env.GITHUB_ACTIONS) { this.writeToStdOut(GH_GROUP_SUFFIX); } } getCommandWithStatus(message, taskStatus) { const commandOutput = pc.dim('> ') + this.formatCommand(this.normalizeMessage(message)); return this.addTaskStatus(taskStatus, commandOutput); } getStatusIcon(taskStatus) { switch (taskStatus) { case 'success': return '✅'; case 'failure': return '❌'; case 'skipped': case 'local-cache-kept-existing': return '⏩'; case 'local-cache': case 'remote-cache': return '🔁'; } } normalizeMessage(message) { if (message.startsWith('nx run ')) { return message.substring('nx run '.length); } else if (message.startsWith('run ')) { return message.substring('run '.length); } else { return message; } } addTaskStatus(taskStatus, commandOutput) { if (taskStatus === 'local-cache') { return `${commandOutput} ${pc.dim('[local cache]')}`; } else if (taskStatus === 'remote-cache') { return `${commandOutput} ${pc.dim('[remote cache]')}`; } else if (taskStatus === 'local-cache-kept-existing') { return `${commandOutput} ${pc.dim('[existing outputs match the cache, left as is]')}`; } else { return commandOutput; } } log({ title, bodyLines, color }) { this.addNewline(); const colorFn = color ? pcColors[color] : undefined; this.writeOutputTitle({ color: 'cyan', title: colorFn ? colorFn(title) : title, }); this.writeOptionalOutputBody(bodyLines); this.addNewline(); } drain() { return new Promise((resolve) => { if (process.stdout.writableNeedDrain) { process.stdout.once('drain', resolve); } else { resolve(); } }); } } exports.output = new CLIOutput();