Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli-utils): Improve log output for check command #199

Merged
merged 16 commits into from
Apr 14, 2024
Merged
5 changes: 5 additions & 0 deletions .changeset/tender-keys-act.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@gql.tada/cli-utils": minor
---

Add `--tsconfig` option to the `check` command, update its log output, and add support for GitHub Actions annotations to it.
20 changes: 15 additions & 5 deletions packages/cli-utils/src/commands/check/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import * as t from 'typanion';
import { Command, Option } from 'clipanion';

import { initTTY } from '../../term';
import { run } from './runner';

export class CheckCommand extends Command {
static paths = [['check']];

tsconfig = Option.String('--tsconfig,-c', {
description: 'Specify the `tsconfig.json` used to read',
});

failOnWarn = Option.Boolean('--fail-on-warn,-w', false, {
description: 'Triggers an error and a non-zero exit code if any warnings have been reported',
});
Expand All @@ -13,12 +19,16 @@ export class CheckCommand extends Command {
Option.String('--level,-l', {
description: 'The minimum severity of diagnostics to display (info, warn, error)',
validator: t.isOneOf([t.isLiteral('info'), t.isLiteral('warn'), t.isLiteral('error')]),
}) || 'error';
}) || 'info';

async execute() {
await run({
failOnWarn: this.failOnWarn,
minSeverity: this.minSeverity,
});
const result = await initTTY().start(
run({
failOnWarn: this.failOnWarn,
minSeverity: this.minSeverity,
tsconfig: this.tsconfig,
})
);
return process.exitCode || (typeof result === 'object' ? result.exit : 0);
}
}
127 changes: 127 additions & 0 deletions packages/cli-utils/src/commands/check/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { pipe, interval, map } from 'wonka';

import * as path from 'node:path';
import * as t from '../../term';
import type { DiagnosticMessage } from './types';
import type { SeveritySummary } from './types';

const CWD = process.cwd();

export function code(text: string) {
return t.text`${t.cmd(t.CSI.Style, t.Style.Underline)}${text}${t.cmd(
t.CSI.Style,
t.Style.NoUnderline
)}`;
}

export function diagnosticFile(filePath: string) {
const relativePath = path.relative(CWD, filePath);
if (!relativePath.startsWith('..')) filePath = relativePath;
return t.text([
t.cmd(t.CSI.Style, t.Style.Underline),
filePath,
t.cmd(t.CSI.Style, t.Style.NoUnderline),
'\n',
]);
}

export function diagnosticMessage(message: DiagnosticMessage) {
const indent = t.Chars.Space.repeat(2);

let color = t.Style.Foreground;
if (message.severity === 'info') {
color = t.Style.BrightBlue;
} else if (message.severity === 'warn') {
color = t.Style.BrightYellow;
} else if (message.severity === 'error') {
color = t.Style.BrightRed;
}

let text = message.message.trim();
if (text.includes('\n')) {
text = text.split('\n').join(t.text([t.Chars.Newline, indent, t.Chars.Tab, t.Chars.Tab]));
}

return t.text([
indent,
t.cmd(t.CSI.Style, t.Style.BrightBlack),
`${message.line}:${message.col}`,
t.Chars.Tab,
t.cmd(t.CSI.Style, color),
message.severity,
t.Chars.Tab,
t.cmd(t.CSI.Style, t.Style.Foreground),
text,
t.Chars.Newline,
]);
}

export function infoSummary(summary: SeveritySummary) {
const { info, error, warn } = summary;
let out = '';
if (info) {
out += t.text([t.cmd(t.CSI.Style, t.Style.Blue), t.Icons.Info, ` ${info} notices\n`]);
}
if (error || warn) {
out += t.text([
t.cmd(t.CSI.Style, t.Style.BrightYellow),
t.Icons.Warning,
` ${error + warn} problems (${error} errors, ${warn} warnings)\n`,
]);
} else {
out += t.text([t.cmd(t.CSI.Style, t.Style.BrightGreen), t.Icons.Tick, ` No problems found\n`]);
}
return out;
}

export function problemsSummary(summary: SeveritySummary) {
const { info, error, warn } = summary;
let out = '';
if (info) {
out += t.text([t.cmd(t.CSI.Style, t.Style.Blue), t.Icons.Info, ` ${info} notices\n`]);
}
out += t.text([
t.cmd(t.CSI.Style, t.Style.Red),
t.Icons.Cross,
` ${error + warn} problems (${error} errors, ${warn} warnings)\n`,
]);
return t.error(out);
}

export function diagnosticMessageGithub(message: DiagnosticMessage): void {
const kind =
message.severity === 'warn' ? 'warning' : message.severity === 'error' ? 'error' : 'notice';
t.githubAnnotation(kind, message.message, {
file: message.file,
line: message.line,
col: message.col,
});
}

export function runningDiagnostics(file: number, ofFiles?: number) {
const progress = ofFiles ? `(${file}/${ofFiles})` : `(${file})`;
return pipe(
interval(150),
map((state) => {
return t.text([
t.cmd(t.CSI.Style, t.Style.Magenta),
t.dotSpinner[state % t.dotSpinner.length],
' ',
t.cmd(t.CSI.Style, t.Style.Foreground),
`Checking files${t.Chars.Ellipsis} `,
t.cmd(t.CSI.Style, t.Style.BrightBlack),
progress,
]);
})
);
}

export function errorMessage(message: string) {
return t.error([
'\n',
t.cmd(t.CSI.Style, [t.Style.Red, t.Style.Invert]),
` ${t.Icons.Warning} Error `,
t.cmd(t.CSI.Style, t.Style.NoInvert),
`\n${message.trim()}\n`,
]);
}
Loading
Loading