nx/packages/cli/lib/output.ts
Marc Abramowitz f17821732b
fix(misc): don't disable chalk when FORCE_COLOR is set (#8226)
* Don't disable chalk when FORCE_COLOR is set

My lint output in Jenkins wasn't colored, which is pretty normal because
a lot of apps when running in Jenkins don't think they have a
color-capable terminal to write to, but I expected that setting the
`FORCE_COLOR` environment variable would work to override this, but I
was surprised to find that it didn't help. Looking at the Nx code, I see
that chalk is turned off whenever `CI` is true, which seems like it
should be refined a bit.

* chore(core): fix code

Co-authored-by: Jason Jean <jasonjean1993@gmail.com>
2022-01-28 20:11:02 -05:00

200 lines
4.5 KiB
TypeScript

/**
* This file has been copied from workspace/src/command-line/output
* Consider that file to be the golden source. Changes (which should be few)
* should be copied here if necessary.
*/
import * as chalk from 'chalk';
import { isCI } from './is_ci';
export interface CLIErrorMessageConfig {
title: string;
bodyLines?: string[];
slug?: string;
}
export interface CLIWarnMessageConfig {
title: string;
bodyLines?: string[];
slug?: string;
}
export interface CLILogMessageConfig {
title: string;
bodyLines?: string[];
}
export interface CLINoteMessageConfig {
title: string;
bodyLines?: string[];
}
export interface CLISuccessMessageConfig {
title: string;
}
/**
* Automatically disable styling applied by chalk if CI=true
*/
const forceColor =
process.env.FORCE_COLOR === '' || process.env.FORCE_COLOR === 'true';
if (isCI() && !forceColor) {
(chalk as any).Level = 0;
}
class CLIOutput {
private readonly NX_PREFIX = `${chalk.cyan(
'>'
)} ${chalk.reset.inverse.bold.cyan(' NX ')}`;
/**
* Longer dash character which forms more of a continuous line when place side to side
* with itself, unlike the standard dash character
*/
private readonly VERTICAL_SEPARATOR =
'———————————————————————————————————————————————';
/**
* 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.
*/
colors = {
gray: chalk.gray,
};
bold = chalk.bold;
underline = chalk.underline;
private writeToStdOut(str: string) {
process.stdout.write(str);
}
private writeOutputTitle({
label,
title,
}: {
label?: string;
title: string;
}): void {
let outputTitle: string;
if (label) {
outputTitle = `${this.NX_PREFIX} ${label} ${title}\n`;
} else {
outputTitle = `${this.NX_PREFIX} ${title}\n`;
}
this.writeToStdOut(outputTitle);
}
private writeOptionalOutputBody(bodyLines?: string[]): void {
if (!bodyLines) {
return;
}
this.addNewline();
bodyLines.forEach((bodyLine) => this.writeToStdOut(` ${bodyLine}\n`));
}
addNewline() {
this.writeToStdOut('\n');
}
addVerticalSeparator() {
this.writeToStdOut(`\n${chalk.gray(this.VERTICAL_SEPARATOR)}\n\n`);
}
error({ title, slug, bodyLines }: CLIErrorMessageConfig) {
this.addNewline();
this.writeOutputTitle({
label: chalk.reset.inverse.bold.red(' ERROR '),
title: chalk.bold.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(
`${chalk.grey(
' Learn more about this error: '
)}https://errors.nx.dev/${slug}\n`
);
}
this.addNewline();
}
warn({ title, slug, bodyLines }: CLIWarnMessageConfig) {
this.addNewline();
this.writeOutputTitle({
label: chalk.reset.inverse.bold.yellow(' WARNING '),
title: chalk.bold.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(
`${chalk.grey(
' Learn more about this warning: '
)}https://errors.nx.dev/${slug}\n`
);
}
this.addNewline();
}
note({ title, bodyLines }: CLINoteMessageConfig) {
this.addNewline();
this.writeOutputTitle({
label: chalk.reset.inverse.bold.keyword('orange')(' NOTE '),
title: chalk.bold.keyword('orange')(title),
});
this.writeOptionalOutputBody(bodyLines);
this.addNewline();
}
success({ title }: CLISuccessMessageConfig) {
this.addNewline();
this.writeOutputTitle({
label: chalk.reset.inverse.bold.green(' SUCCESS '),
title: chalk.bold.green(title),
});
this.addNewline();
}
logSingleLine(message: string) {
this.addNewline();
this.writeOutputTitle({
title: message,
});
this.addNewline();
}
log({ title, bodyLines }: CLIWarnMessageConfig) {
this.addNewline();
this.writeOutputTitle({
title: chalk.white(title),
});
this.writeOptionalOutputBody(bodyLines);
this.addNewline();
}
}
export const output = new CLIOutput();