2023-02-17 15:17:54 -05:00

248 lines
5.4 KiB
TypeScript

/*
* Because we don't want to depend on @nrwl/workspace (to speed up the workspace creation)
* we duplicate the helper functions from @nrwl/workspace in this file.
*/
import * as chalk from 'chalk';
import { EOL } from 'os';
export function isCI() {
return (
process.env.CI === 'true' ||
process.env.TF_BUILD === 'true' ||
process.env.GITHUB_ACTIONS === 'true' ||
process.env.BUILDKITE === 'true' ||
process.env.CIRCLECI === 'true' ||
process.env.CIRRUS_CI === 'true' ||
process.env.TRAVIS === 'true' ||
!!process.env['bamboo.buildKey'] ||
!!process.env.CODEBUILD_BUILD_ID ||
!!process.env.GITLAB_CI ||
!!process.env.HEROKU_TEST_RUN_ID ||
!!process.env.BUILD_ID ||
!!process.env.BUILD_BUILDID ||
!!process.env.TEAMCITY_VERSION
);
}
export interface CLIErrorMessageConfig {
title: string;
bodyLines?: string[];
slug?: string;
}
export interface CLIWarnMessageConfig {
title: string;
bodyLines?: string[];
slug?: string;
}
export interface CLINoteMessageConfig {
title: string;
bodyLines?: string[];
}
export interface CLISuccessMessageConfig {
title: string;
bodyLines?: string[];
}
/**
* Automatically disable styling applied by chalk if CI=true
*/
if (isCI()) {
(chalk as any).level = 0;
}
class CLIOutput {
readonly X_PADDING = ' ';
/**
* Longer dash character which forms more of a continuous line when place side to side
* with itself, unlike the standard dash character
*/
private get VERTICAL_SEPARATOR() {
let divider = '';
for (
let i = 0;
i < process.stdout.columns - this.X_PADDING.length * 2;
i++
) {
divider += '\u2014';
}
return divider;
}
/**
* 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,
green: chalk.green,
red: chalk.red,
cyan: chalk.cyan,
white: chalk.white,
};
bold = chalk.bold;
underline = chalk.underline;
dim = chalk.dim;
private writeToStdOut(str: string) {
process.stdout.write(str);
}
private writeOutputTitle({
color,
title,
}: {
color: string;
title: string;
}): void {
this.writeToStdOut(` ${this.applyNxPrefix(color, title)}${EOL}`);
}
private writeOptionalOutputBody(bodyLines?: string[]): void {
if (!bodyLines) {
return;
}
this.addNewline();
bodyLines.forEach((bodyLine) => this.writeToStdOut(` ${bodyLine}${EOL}`));
}
applyNxPrefix(color = 'cyan', text: string): string {
let nxPrefix = '';
if (chalk[color]) {
nxPrefix = `${chalk[color]('>')} ${chalk.reset.inverse.bold[color](
' NX '
)}`;
} else {
nxPrefix = `${chalk.keyword(color)(
'>'
)} ${chalk.reset.inverse.bold.keyword(color)(' NX ')}`;
}
return `${nxPrefix} ${text}`;
}
addNewline() {
this.writeToStdOut(EOL);
}
addVerticalSeparator(color = 'gray') {
this.addNewline();
this.addVerticalSeparatorWithoutNewLines(color);
this.addNewline();
}
addVerticalSeparatorWithoutNewLines(color = 'gray') {
this.writeToStdOut(
`${this.X_PADDING}${chalk.dim[color](this.VERTICAL_SEPARATOR)}${EOL}`
);
}
error({ title, slug, bodyLines }: CLIErrorMessageConfig) {
this.addNewline();
this.writeOutputTitle({
color: 'red',
title: chalk.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}${EOL}`
);
}
this.addNewline();
}
warn({ title, slug, bodyLines }: CLIWarnMessageConfig) {
this.addNewline();
this.writeOutputTitle({
color: 'yellow',
title: chalk.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({
color: 'orange',
title: chalk.keyword('orange')(title),
});
this.writeOptionalOutputBody(bodyLines);
this.addNewline();
}
success({ title, bodyLines }: CLISuccessMessageConfig) {
this.addNewline();
this.writeOutputTitle({
color: 'green',
title: chalk.green(title),
});
this.writeOptionalOutputBody(bodyLines);
this.addNewline();
}
logSingleLine(message: string) {
this.addNewline();
this.writeOutputTitle({
color: 'gray',
title: message,
});
this.addNewline();
}
logCommand(message: string) {}
log({ title, bodyLines, color }: CLIWarnMessageConfig & { color?: string }) {
this.addNewline();
this.writeOutputTitle({
color: 'cyan',
title: color ? chalk[color](title) : title,
});
this.writeOptionalOutputBody(bodyLines);
this.addNewline();
}
}
export const output = new CLIOutput();