Skip to content

Commit 783555d

Browse files
committed
Expose renderer in CLI package
1 parent 0224946 commit 783555d

File tree

8 files changed

+72
-49
lines changed

8 files changed

+72
-49
lines changed

packages/cli/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,16 @@
2121
},
2222
"files": [
2323
"LICENSE",
24-
"dist/**/*.js"
24+
"dist/**/*.js",
25+
"dist/**/*.js.map",
26+
"dist/**/*.d.ts"
2527
],
2628
"bin": {
2729
"attw": "./dist/index.js"
2830
},
31+
"exports": {
32+
"./internal/render": "./dist/render/index.js"
33+
},
2934
"publishConfig": {
3035
"access": "public"
3136
},

packages/cli/src/index.ts

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,20 @@ import { major, minor } from "semver";
1818
const packageJson = createRequire(import.meta.url)("../package.json");
1919
const version = packageJson.version;
2020

21-
const formats = ["auto", "table", "table-flipped", "ascii", "json"] as const;
22-
23-
type Format = (typeof formats)[number];
24-
25-
export interface Opts {
21+
const formats = Object.keys({
22+
auto: true,
23+
json: true,
24+
ascii: true,
25+
table: true,
26+
"table-flipped": true,
27+
} satisfies Record<render.Format, any>) as render.Format[];
28+
29+
interface Opts extends render.RenderOptions {
2630
pack?: boolean;
2731
fromNpm?: boolean;
2832
definitelyTyped?: boolean | string;
29-
summary?: boolean;
30-
emoji?: boolean;
31-
color?: boolean;
3233
quiet?: boolean;
3334
configPath?: string;
34-
ignoreRules?: string[];
35-
format: Format;
3635

3736
entrypoints?: string[];
3837
includeEntrypoints?: string[];
@@ -81,9 +80,6 @@ particularly ESM-related module resolution issues.`,
8180
.action(async (fileOrDirectory = ".") => {
8281
const opts = program.opts<Opts>();
8382
await readConfig(program, opts.configPath);
84-
opts.ignoreRules = opts.ignoreRules?.map(
85-
(value) => Object.keys(problemFlags).find((key) => problemFlags[key as core.ProblemKind] === value) as string,
86-
);
8783

8884
if (opts.quiet) {
8985
console.log = () => {};
@@ -210,21 +206,27 @@ particularly ESM-related module resolution issues.`,
210206

211207
console.log(JSON.stringify(result));
212208

213-
if (analysis.types && analysis.problems.some((problem) => !opts.ignoreRules?.includes(problem.kind)))
209+
if (
210+
analysis.types &&
211+
analysis.problems.some((problem) => !opts.ignoreRules?.includes(problemFlags[problem.kind]))
212+
)
214213
process.exit(1);
215214

216215
return;
217216
}
218217

219218
console.log();
220219
if (analysis.types) {
221-
await render.typed(analysis, opts);
220+
console.log(await render.typed(analysis, opts));
222221

223-
if (analysis.types && analysis.problems.some((problem) => !opts.ignoreRules?.includes(problem.kind))) {
222+
if (
223+
analysis.types &&
224+
analysis.problems.some((problem) => !opts.ignoreRules?.includes(problemFlags[problem.kind]))
225+
) {
224226
process.exitCode = 1;
225227
}
226228
} else {
227-
render.untyped(analysis as core.UntypedResult);
229+
console.log(render.untyped(analysis as core.UntypedResult));
228230
}
229231

230232
if (deleteTgz) {

packages/cli/src/problemUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as core from "@arethetypeswrong/core";
22
import type { ProblemKind } from "@arethetypeswrong/core";
33

4-
export const problemFlags: Record<ProblemKind, string> = {
4+
export const problemFlags = {
55
NoResolution: "no-resolution",
66
UntypedResolution: "untyped-resolution",
77
FalseCJS: "false-cjs",
@@ -13,7 +13,7 @@ export const problemFlags: Record<ProblemKind, string> = {
1313
MissingExportEquals: "missing-export-equals",
1414
UnexpectedModuleSyntax: "unexpected-module-syntax",
1515
InternalResolutionError: "internal-resolution-error",
16-
};
16+
} as const satisfies Record<ProblemKind, string>;
1717

1818
export const resolutionKinds: Record<core.ResolutionKind, string> = {
1919
node10: "node10",

packages/cli/src/render/index.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,13 @@
1+
import type { problemFlags } from "../problemUtils.js";
2+
3+
export type Format = "auto" | "table" | "table-flipped" | "ascii" | "json";
4+
export interface RenderOptions {
5+
ignoreRules?: (typeof problemFlags)[keyof typeof problemFlags][];
6+
format?: Format;
7+
color?: boolean;
8+
summary?: boolean;
9+
emoji?: boolean;
10+
}
11+
112
export * from "./typed.js";
213
export * from "./untyped.js";

packages/cli/src/render/typed.ts

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,44 @@
11
import * as core from "@arethetypeswrong/core";
2+
import { filterProblems, problemAffectsEntrypoint, problemKindInfo } from "@arethetypeswrong/core/problems";
23
import { allResolutionKinds, getResolutionOption, groupProblemsByKind } from "@arethetypeswrong/core/utils";
34
import chalk from "chalk";
45
import Table, { type GenericTable, type HorizontalTableRow } from "cli-table3";
56
import { marked } from "marked";
6-
7-
import { filterProblems, problemAffectsEntrypoint, problemKindInfo } from "@arethetypeswrong/core/problems";
8-
import type { Opts } from "../index.js";
7+
import TerminalRenderer from "marked-terminal";
98
import { moduleKinds, problemFlags, resolutionKinds } from "../problemUtils.js";
109
import { asciiTable } from "./asciiTable.js";
11-
import TerminalRenderer from "marked-terminal";
10+
import type { RenderOptions } from "./index.js";
1211

13-
export async function typed(analysis: core.Analysis, opts: Opts) {
14-
const problems = analysis.problems.filter((problem) => !opts.ignoreRules || !opts.ignoreRules.includes(problem.kind));
12+
export async function typed(analysis: core.Analysis, opts: RenderOptions): Promise<string> {
13+
let output = "";
14+
const problems = analysis.problems.filter(
15+
(problem) => !opts.ignoreRules || !opts.ignoreRules.includes(problemFlags[problem.kind]),
16+
);
1517
const grouped = groupProblemsByKind(problems);
1618
const entrypoints = Object.keys(analysis.entrypoints);
1719
marked.setOptions({
1820
renderer: new TerminalRenderer(),
1921
});
2022

21-
console.log(`${analysis.packageName} v${analysis.packageVersion}`);
23+
out(`${analysis.packageName} v${analysis.packageVersion}`);
2224
if (analysis.types.kind === "@types") {
23-
console.log(`${analysis.types.packageName} v${analysis.types.packageVersion}`);
25+
out(`${analysis.types.packageName} v${analysis.types.packageVersion}`);
2426
}
25-
console.log();
27+
out();
2628
if (Object.keys(analysis.buildTools).length) {
27-
console.log("Build tools:");
28-
console.log(
29+
out("Build tools:");
30+
out(
2931
Object.entries(analysis.buildTools)
3032
.map(([tool, version]) => {
3133
return `- ${tool}@${version}`;
3234
})
3335
.join("\n"),
3436
);
35-
console.log();
37+
out();
3638
}
3739

3840
if (opts.ignoreRules && opts.ignoreRules.length) {
39-
console.log(
40-
chalk.gray(
41-
` (ignoring rules: ${opts.ignoreRules
42-
.map((rule) => `'${problemFlags[rule as core.ProblemKind]}'`)
43-
.join(", ")})\n`,
44-
),
45-
);
41+
out(chalk.gray(` (ignoring rules: ${opts.ignoreRules.map((rule) => `'${rule}'`).join(", ")})\n`));
4642
}
4743

4844
if (opts.summary) {
@@ -54,7 +50,7 @@ export async function typed(analysis: core.Analysis, opts: Opts) {
5450
return `${emoji}${description}`;
5551
});
5652

57-
console.log(summaryTexts.join("") || defaultSummary);
53+
out(summaryTexts.join("") || defaultSummary);
5854
}
5955

6056
const entrypointNames = entrypoints.map(
@@ -119,25 +115,31 @@ export async function typed(analysis: core.Analysis, opts: Opts) {
119115

120116
switch (opts.format) {
121117
case "table":
122-
console.log(table!.toString());
118+
out(table!.toString());
123119
break;
124120
case "table-flipped":
125-
console.log(flippedTable!.toString());
121+
out(flippedTable!.toString());
126122
break;
127123
case "ascii":
128-
console.log(asciiTable(table!));
124+
out(asciiTable(table!));
129125
break;
130126
case "auto":
131127
const terminalWidth = process.stdout.columns || 133; // This looks like GitHub Actions' width
132128
if (table!.width <= terminalWidth) {
133-
console.log(table!.toString());
129+
out(table!.toString());
134130
} else if (flippedTable!.width <= terminalWidth) {
135-
console.log(flippedTable!.toString());
131+
out(flippedTable!.toString());
136132
} else {
137-
console.log(asciiTable(table!));
133+
out(asciiTable(table!));
138134
}
139135
break;
140136
}
137+
138+
return output.trimEnd();
139+
140+
function out(s: string = "") {
141+
output += s + "\n";
142+
}
141143
}
142144

143145
function memo<Args extends (string | number)[], Result>(fn: (...args: Args) => Result): (...args: Args) => Result {

packages/cli/src/render/untyped.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as core from "@arethetypeswrong/core";
22

33
export function untyped(analysis: core.UntypedResult) {
4-
console.log("This package does not contain types.\nDetails: ", analysis);
4+
return "This package does not contain types.\nDetails: " + JSON.stringify(analysis, null, 2);
55
}

packages/cli/test/snapshots/[email protected]

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ $ attw [email protected] -f table-flipped
55
66
77
This package does not contain types.
8-
Details: { packageName: 'ejs', packageVersion: '3.1.9', types: false }
8+
Details: {
9+
"packageName": "ejs",
10+
"packageVersion": "3.1.9",
11+
"types": false
12+
}
913
1014
1115
```

packages/cli/tsconfig.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"rootDir": "src",
66
"types": ["ts-expose-internals", "node"],
77
"outDir": "./dist",
8-
"declarationDir": "./lib",
98
"sourceMap": true
109
},
1110
"include": ["src"],

0 commit comments

Comments
 (0)