@arethetypeswrong/cli
Advanced tools
Comparing version 0.16.4 to 0.17.0
import { problemFlags } from "./problemUtils.js"; | ||
export function getExitCode(analysis, opts) { | ||
var _a, _b; | ||
if (!analysis.types) { | ||
return 0; | ||
} | ||
if (!(opts === null || opts === void 0 ? void 0 : opts.ignoreRules)) { | ||
return analysis.problems.length > 0 ? 1 : 0; | ||
} | ||
return analysis.problems.some((problem) => !opts.ignoreRules.includes(problemFlags[problem.kind])) ? 1 : 0; | ||
const ignoreRules = (_a = opts === null || opts === void 0 ? void 0 : opts.ignoreRules) !== null && _a !== void 0 ? _a : []; | ||
const ignoreResolutions = (_b = opts === null || opts === void 0 ? void 0 : opts.ignoreResolutions) !== null && _b !== void 0 ? _b : []; | ||
return analysis.problems.some((problem) => { | ||
const notRuleIgnored = !ignoreRules.includes(problemFlags[problem.kind]); | ||
const notResolutionIgnored = "resolutionKind" in problem ? !ignoreResolutions.includes(problem.resolutionKind) : true; | ||
return notRuleIgnored && notResolutionIgnored; | ||
}) ? 1 : 0; | ||
} | ||
//# sourceMappingURL=getExitCode.js.map |
@@ -17,2 +17,3 @@ #!/usr/bin/env node | ||
import { getExitCode } from "./getExitCode.js"; | ||
import { applyProfile, profiles } from "./profiles.js"; | ||
const packageJson = createRequire(import.meta.url)("../package.json"); | ||
@@ -49,2 +50,3 @@ const version = packageJson.version; | ||
.addOption(new Option("--ignore-rules <rules...>", "Specify rules to ignore").choices(Object.values(problemFlags)).default([])) | ||
.addOption(new Option("--profile <profile>", "Specify analysis profile").choices(Object.keys(profiles)).default("strict")) | ||
.option("--summary, --no-summary", "Whether to print summary information about the different errors") | ||
@@ -57,2 +59,5 @@ .option("--emoji, --no-emoji", "Whether to use any emojis") | ||
await readConfig(program, opts.configPath); | ||
if (opts.profile) { | ||
applyProfile(opts.profile, opts); | ||
} | ||
if (opts.quiet) { | ||
@@ -59,0 +64,0 @@ console.log = () => { }; |
import { Command } from "commander"; | ||
import { readFile } from "fs/promises"; | ||
import { problemFlags } from "./problemUtils.js"; | ||
import { profiles } from "./profiles.js"; | ||
export async function readConfig(program, alternate = ".attw.json") { | ||
@@ -21,2 +22,8 @@ try { | ||
} | ||
if (key === "profile") { | ||
if (typeof value !== "string") | ||
program.error(`error: config option 'profile' should be a string.`); | ||
if (!(value in profiles)) | ||
program.error(`error: config option 'profile' argument '${value}' is invalid. Allowed choices are ${Object.keys(profiles).join(", ")}.`); | ||
} | ||
if (Array.isArray(value)) { | ||
@@ -23,0 +30,0 @@ const opt = program.getOptionValue(key); |
@@ -1,5 +0,6 @@ | ||
import type { problemFlags } from "../problemUtils.js"; | ||
import type { problemFlags, resolutionKinds } from "../problemUtils.js"; | ||
export type Format = "auto" | "table" | "table-flipped" | "ascii" | "json"; | ||
export interface RenderOptions { | ||
ignoreRules?: (typeof problemFlags)[keyof typeof problemFlags][]; | ||
ignoreResolutions?: (keyof typeof resolutionKinds)[]; | ||
format?: Format; | ||
@@ -6,0 +7,0 @@ color?: boolean; |
import * as core from "@arethetypeswrong/core"; | ||
import type { RenderOptions } from "./index.js"; | ||
export declare function typed(analysis: core.Analysis, { emoji, summary, format, ignoreRules }: RenderOptions): Promise<string>; | ||
export declare function typed(analysis: core.Analysis, { emoji, summary, format, ignoreRules, ignoreResolutions }: RenderOptions): Promise<string>; | ||
//# sourceMappingURL=typed.d.ts.map |
import * as core from "@arethetypeswrong/core"; | ||
import { filterProblems, problemAffectsEntrypoint, problemKindInfo } from "@arethetypeswrong/core/problems"; | ||
import { filterProblems, problemAffectsEntrypoint, problemAffectsResolutionKind, problemKindInfo, } from "@arethetypeswrong/core/problems"; | ||
import { allResolutionKinds, getResolutionOption, groupProblemsByKind } from "@arethetypeswrong/core/utils"; | ||
@@ -10,6 +10,9 @@ import chalk from "chalk"; | ||
import { asciiTable } from "./asciiTable.js"; | ||
export async function typed(analysis, { emoji = true, summary = true, format = "auto", ignoreRules = [] }) { | ||
export async function typed(analysis, { emoji = true, summary = true, format = "auto", ignoreRules = [], ignoreResolutions = [] }) { | ||
let output = ""; | ||
const problems = analysis.problems.filter((problem) => !ignoreRules || !ignoreRules.includes(problemFlags[problem.kind])); | ||
const grouped = groupProblemsByKind(problems); | ||
// sort resolutions with required (impacts result) first and ignored after | ||
const requiredResolutions = allResolutionKinds.filter((kind) => !ignoreResolutions.includes(kind)); | ||
const ignoredResolutions = allResolutionKinds.filter((kind) => ignoreResolutions.includes(kind)); | ||
const resolutions = requiredResolutions.concat(ignoredResolutions); | ||
const entrypoints = Object.keys(analysis.entrypoints); | ||
@@ -36,8 +39,13 @@ marked.setOptions({ | ||
} | ||
if (ignoreResolutions && ignoreResolutions.length) { | ||
out(chalk.gray(` (ignoring resolutions: ${ignoreResolutions.map((resolution) => `'${resolution}'`).join(", ")})\n`)); | ||
} | ||
if (summary) { | ||
const defaultSummary = marked(!emoji ? " No problems found" : " No problems found ๐"); | ||
const summaryTexts = Object.keys(grouped).map((kind) => { | ||
const grouped = groupProblemsByKind(problems); | ||
const summaryTexts = Object.entries(grouped).map(([kind, kindProblems]) => { | ||
const info = problemKindInfo[kind]; | ||
const affectsRequiredResolution = kindProblems.some((p) => requiredResolutions.some((r) => problemAffectsResolutionKind(p, r, analysis))); | ||
const description = marked(`${info.description}${info.details ? ` Use \`-f json\` to see ${info.details}.` : ""} ${info.docsUrl}`); | ||
return `${emoji ? `${info.emoji} ` : ""}${description}`; | ||
return `${affectsRequiredResolution ? "" : "(ignored per resolution) "}${emoji ? `${info.emoji} ` : ""}${description}`; | ||
}); | ||
@@ -54,2 +62,3 @@ out(summaryTexts.join("") || defaultSummary); | ||
var _a, _b, _c; | ||
const ignoredPrefix = ignoreResolutions.includes(resolutionKind) ? "(ignored) " : ""; | ||
const problemsForCell = groupProblemsByKind(filterProblems(problems, analysis, { entrypoint: subpath, resolutionKind })); | ||
@@ -61,3 +70,3 @@ const entrypoint = analysis.entrypoints[subpath].resolutions[resolutionKind]; | ||
return kinds | ||
.map((kind) => (emoji ? `${problemKindInfo[kind].emoji} ` : "") + problemKindInfo[kind].shortDescription) | ||
.map((kind) => ignoredPrefix + (emoji ? `${problemKindInfo[kind].emoji} ` : "") + problemKindInfo[kind].shortDescription) | ||
.join("\n"); | ||
@@ -70,7 +79,10 @@ } | ||
moduleKinds[((_c = (_a = analysis.programInfo[getResolutionOption(resolutionKind)].moduleKinds) === null || _a === void 0 ? void 0 : _a[(_b = resolution === null || resolution === void 0 ? void 0 : resolution.fileName) !== null && _b !== void 0 ? _b : ""]) === null || _c === void 0 ? void 0 : _c.detectedKind) || ""]; | ||
return (resolution === null || resolution === void 0 ? void 0 : resolution.isJson) ? jsonResult : moduleResult; | ||
return ignoredPrefix + ((resolution === null || resolution === void 0 ? void 0 : resolution.isJson) ? jsonResult : moduleResult); | ||
}); | ||
const flippedTable = format === "auto" || format === "table-flipped" | ||
? new Table({ | ||
head: ["", ...allResolutionKinds.map((kind) => chalk.reset(resolutionKinds[kind]))], | ||
head: [ | ||
"", | ||
...resolutions.map((kind) => chalk.reset(resolutionKinds[kind] + (ignoreResolutions.includes(kind) ? " (ignored)" : ""))), | ||
], | ||
}) | ||
@@ -82,3 +94,3 @@ : undefined; | ||
entrypointHeaders[i], | ||
...allResolutionKinds.map((resolutionKind) => getCellContents(subpath, resolutionKind)), | ||
...resolutions.map((resolutionKind) => getCellContents(subpath, resolutionKind)), | ||
]); | ||
@@ -93,3 +105,3 @@ }); | ||
if (table) { | ||
allResolutionKinds.forEach((kind) => { | ||
resolutions.forEach((kind) => { | ||
table.push([resolutionKinds[kind], ...entrypoints.map((entrypoint) => getCellContents(entrypoint, kind))]); | ||
@@ -96,0 +108,0 @@ }); |
{ | ||
"name": "@arethetypeswrong/cli", | ||
"version": "0.16.4", | ||
"version": "0.17.0", | ||
"description": "A CLI tool for arethetypeswrong.github.io", | ||
@@ -54,3 +54,3 @@ "author": "Andrew Branch & ej-shafran", | ||
"semver": "^7.5.4", | ||
"@arethetypeswrong/core": "0.16.4" | ||
"@arethetypeswrong/core": "0.17.0" | ||
}, | ||
@@ -64,4 +64,4 @@ "engines": { | ||
"local:uninstall": "npm uninstall -g @arethetypeswrong/cli", | ||
"test": "tsc -b test && node --test 'test/dist/**/*.test.js'" | ||
"test": "tsc -b test && node --test \"test/dist/**/*.test.js\"" | ||
} | ||
} |
@@ -157,2 +157,20 @@ # arethetypeswrong/cli | ||
#### Profiles | ||
Profiles select a set of resolution modes to require/ignore. All are evaluated but failures outside of those required are ignored. | ||
The available profiles are: | ||
- `strict` - requires all resolutions | ||
- `node16` - ignores node10 resolution failures | ||
- `esm-only` - ignores CJS resolution failures | ||
In the CLI: `--profile` | ||
```shell | ||
attw <file-name> --profile <profile> | ||
``` | ||
In the config file, `profile` can be a string value. | ||
#### Ignore Rules | ||
@@ -159,0 +177,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
56883
30
537
263
+ Added@arethetypeswrong/core@0.17.0(transitive)
- Removed@arethetypeswrong/core@0.16.4(transitive)