From a76facebeb4524bf88b67577b1311a51f515dd72 Mon Sep 17 00:00:00 2001 From: Jason Hartman Date: Thu, 19 Sep 2024 17:51:21 -0700 Subject: [PATCH] feat: replace ignore-resolutions with profile Add four profiles: - `strict` - same as today; all resolutions - `node16` - ignores node10 resolution failures - `esm-only` - ignores CJS resolution failures - `node16-only` - strictly node16 resolutions --- .changeset/fuzzy-cats-shed.md | 2 +- packages/cli/src/index.ts | 13 +++++++++---- packages/cli/src/profiles.ts | 29 +++++++++++++++++++++++++++++ packages/cli/src/readConfig.ts | 14 +++++++------- 4 files changed, 46 insertions(+), 12 deletions(-) create mode 100644 packages/cli/src/profiles.ts diff --git a/.changeset/fuzzy-cats-shed.md b/.changeset/fuzzy-cats-shed.md index 2e03f0f..0de30de 100644 --- a/.changeset/fuzzy-cats-shed.md +++ b/.changeset/fuzzy-cats-shed.md @@ -2,4 +2,4 @@ "@arethetypeswrong/core": minor --- -Add --ignore-resolutions cli option. Example: --ignore-resolutions node10 +Add --profile cli option. Example: --profile node16 diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 545a8f1..b17786c 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -10,11 +10,12 @@ import { readFile, stat, unlink } from "fs/promises"; import { createRequire } from "module"; import path from "path"; import readline from "readline"; -import { problemFlags, resolutionKinds } from "./problemUtils.js"; +import { problemFlags } from "./problemUtils.js"; import { readConfig } from "./readConfig.js"; import * as render from "./render/index.js"; import { major, minor } from "semver"; import { getExitCode } from "./getExitCode.js"; +import { applyProfile, profiles } from "./profiles.js"; const packageJson = createRequire(import.meta.url)("../package.json"); const version = packageJson.version; @@ -28,6 +29,8 @@ const formats = Object.keys({ } satisfies Record) as render.Format[]; interface Opts extends render.RenderOptions { + profile?: keyof typeof profiles; + pack?: boolean; fromNpm?: boolean; definitelyTyped?: boolean | string; @@ -81,9 +84,7 @@ particularly ESM-related module resolution issues.`, new Option("--ignore-rules ", "Specify rules to ignore").choices(Object.values(problemFlags)).default([]), ) .addOption( - new Option("--ignore-resolutions ", "Specify resolutions to ignore") - .choices(Object.keys(resolutionKinds)) - .default([]), + new Option("--profile ", "Specify analysis profile").choices(Object.keys(profiles)).default("strict"), ) .option("--summary, --no-summary", "Whether to print summary information about the different errors") .option("--emoji, --no-emoji", "Whether to use any emojis") @@ -93,6 +94,10 @@ particularly ESM-related module resolution issues.`, const opts = program.opts(); await readConfig(program, opts.configPath); + if (opts.profile) { + applyProfile(opts.profile, opts); + } + if (opts.quiet) { console.log = () => {}; } diff --git a/packages/cli/src/profiles.ts b/packages/cli/src/profiles.ts new file mode 100644 index 0000000..7d392c2 --- /dev/null +++ b/packages/cli/src/profiles.ts @@ -0,0 +1,29 @@ +import type { RenderOptions } from "./render/index.js"; + +type Profile = Pick, "ignoreResolutions">; + +export const profiles = { + strict: { + ignoreResolutions: [], + }, + node16: { + ignoreResolutions: ["node10"], + }, + "esm-only": { + ignoreResolutions: ["node10", "node16-cjs"], + }, + "node16-only": { + ignoreResolutions: ["node10", "bundler"], + }, +} satisfies Record; + +/** + * Merges the profile with the provided options + * + * @param profileKey - name of the profile to apply + * @param opts - options to apply the profile to + */ +export function applyProfile(profileKey: keyof typeof profiles, opts: RenderOptions): void { + const profile = profiles[profileKey]; + opts.ignoreResolutions = (opts.ignoreResolutions ?? []).concat(profile.ignoreResolutions); +} diff --git a/packages/cli/src/readConfig.ts b/packages/cli/src/readConfig.ts index c4782e8..3ae3e81 100644 --- a/packages/cli/src/readConfig.ts +++ b/packages/cli/src/readConfig.ts @@ -1,6 +1,7 @@ import { Command } from "commander"; import { readFile } from "fs/promises"; -import { problemFlags, resolutionKinds } from "./problemUtils.js"; +import { problemFlags } from "./problemUtils.js"; +import { profiles } from "./profiles.js"; export async function readConfig(program: Command, alternate = ".attw.json") { try { @@ -25,13 +26,12 @@ export async function readConfig(program: Command, alternate = ".attw.json") { ); } - if (key === "ignoreResolutions") { - if (!Array.isArray(value)) program.error(`error: config option 'ignoreResolutions' should be an array.`); - const invalid = value.find((resolution) => !Object.keys(resolutionKinds).includes(resolution)); - if (invalid) + 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 'ignoreResolutions' argument '${invalid}' is invalid. Allowed choices are ${Object.keys( - resolutionKinds, + `error: config option 'profile' argument '${value}' is invalid. Allowed choices are ${Object.keys( + profiles, ).join(", ")}.`, ); }