From 2439b60598b5f7297dc93cbc0a9d0dc42c6a90b3 Mon Sep 17 00:00:00 2001 From: Graham Vasquez Date: Fri, 27 Oct 2023 11:31:33 -0400 Subject: [PATCH 1/5] bug: account for base when suggesting rerun cmd Add additional filter logic to check if an options entry was excluded by the base, and filter it out of the suggested rerun flags --- src/create/createRerunSuggestion.ts | 12 ++++- .../options/augmentOptionsWithExcludes.ts | 52 +++++++++++-------- 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/src/create/createRerunSuggestion.ts b/src/create/createRerunSuggestion.ts index 0af404577..4ab1c9843 100644 --- a/src/create/createRerunSuggestion.ts +++ b/src/create/createRerunSuggestion.ts @@ -1,4 +1,8 @@ import { allArgOptions } from "../shared/options/args.js"; +import { + ExclusionKey, + getExclusions, +} from "../shared/options/augmentOptionsWithExcludes.js"; import { Options } from "../shared/types.js"; function getFirstMatchingArg(key: string) { @@ -30,10 +34,16 @@ export function createRerunSuggestion(options: Partial): string { }; const args = Object.entries(optionsNormalized) + // Sort so the base is first, then the rest are compared using the `localeCompare` string method .sort(([a], [b]) => a === "base" ? -1 : b === "base" ? 1 : a.localeCompare(b), ) - .filter(([, value]) => !!value) + // Filter out all entries that have a key in the excluded object or have a falsey value + .filter( + ([key, value]) => + getExclusions(options, optionsNormalized.base)[key as ExclusionKey] == + undefined && !!value, + ) .map(([key, value]) => { return `--${getFirstMatchingArg(key)} ${stringifyValue(value)}`; }) diff --git a/src/shared/options/augmentOptionsWithExcludes.ts b/src/shared/options/augmentOptionsWithExcludes.ts index 366deb1f4..aa67871c4 100644 --- a/src/shared/options/augmentOptionsWithExcludes.ts +++ b/src/shared/options/augmentOptionsWithExcludes.ts @@ -10,7 +10,7 @@ interface ExclusionDescription { uncommon?: true; } -type ExclusionKey = keyof Options & `exclude${string}`; +export type ExclusionKey = keyof Options & `exclude${string}`; const exclusionDescriptions: Record = { excludeAllContributors: { @@ -119,6 +119,34 @@ const exclusionDescriptions: Record = { const exclusionKeys = Object.keys(exclusionDescriptions) as ExclusionKey[]; +export function getExclusions( + options: Partial, + base?: OptionsBase, +): Partial { + switch (base) { + case "common": + return { + ...Object.fromEntries( + exclusionKeys + .filter((exclusion) => exclusionDescriptions[exclusion].uncommon) + .map((exclusion) => [exclusion, options[exclusion] ?? true]), + ), + }; + case "minimum": + return { + ...Object.fromEntries( + exclusionKeys.map((exclusion) => [ + exclusion, + options[exclusion] ?? true, + ]), + ), + }; + // We only really care about exclusions on the common and minimum bases + default: + return {}; + } +} + export async function augmentOptionsWithExcludes( options: Options, ): Promise { @@ -172,31 +200,13 @@ export async function augmentOptionsWithExcludes( switch (base) { case undefined: return undefined; - case "common": - return { - ...options, - ...Object.fromEntries( - exclusionKeys - .filter((exclusion) => exclusionDescriptions[exclusion].uncommon) - .map((exclusion) => [exclusion, options[exclusion] ?? true]), - ), - }; - - case "everything": - return options; - case "minimum": + case "everything": return { ...options, - ...Object.fromEntries( - exclusionKeys.map((exclusion) => [ - exclusion, - options[exclusion] ?? true, - ]), - ), + ...getExclusions(options, base), }; - case "prompt": const exclusionsNotEnabled = new Set( filterPromptCancel( From 786b124687e5a2c9a22659e80b43edf79ae638af Mon Sep 17 00:00:00 2001 From: Graham Vasquez Date: Sat, 28 Oct 2023 08:37:44 -0700 Subject: [PATCH 2/5] add new test, update failing test with suggestion from jest --- src/create/createRerunSuggestion.test.ts | 27 +++++++++++++++++++ .../augmentOptionsWithExcludes.test.ts | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/create/createRerunSuggestion.test.ts b/src/create/createRerunSuggestion.test.ts index 0ba4444e2..556685671 100644 --- a/src/create/createRerunSuggestion.test.ts +++ b/src/create/createRerunSuggestion.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it } from "vitest"; +import { getExclusions } from "../shared/options/augmentOptionsWithExcludes.js"; import { Options } from "../shared/types.js"; import { createRerunSuggestion } from "./createRerunSuggestion.js"; @@ -93,4 +94,30 @@ describe("createRerunSuggestion", () => { '"npx create-typescript-app --mode initialize --base everything --access public --author TestAuthor --description \\"Test description.\\" --directory . --email-github github@email.com --email-npm npm@email.com --exclude-all-contributors true --exclude-compliance true --exclude-lint-jsdoc true --exclude-lint-json true --exclude-lint-knip true --exclude-lint-md true --exclude-lint-package-json true --exclude-lint-perfectionist true --exclude-lint-spelling true --keywords \\"abc def ghi jkl mno pqr\\" --mode initialize --owner TestOwner --repository test-repository --skip-github-api true --skip-install true --skip-removal true --title \\"Test Title\\""', ); }); + + it("does not list all excludes when using common or minimum base", () => { + const opts = { + ...options, + excludeLintKnip: undefined, + }; + const common = createRerunSuggestion({ + ...opts, + base: "common", + ...getExclusions(options, "common"), + }); + + expect(common).toMatchInlineSnapshot( + '"npx create-typescript-app --mode create --base common --access public --author TestAuthor --description \\"Test description.\\" --directory . --email-github github@email.com --email-npm npm@email.com --exclude-all-contributors true --keywords \\"abc def ghi jkl mno pqr\\" --mode create --owner TestOwner --repository test-repository --skip-github-api true --skip-install true --skip-removal true --title \\"Test Title\\""', + ); + + const minimum = createRerunSuggestion({ + ...opts, + base: "minimum", + ...getExclusions(options, "minimum"), + }); + + expect(minimum).toMatchInlineSnapshot( + '"npx create-typescript-app --mode create --base minimum --access public --author TestAuthor --description \\"Test description.\\" --directory . --email-github github@email.com --email-npm npm@email.com --keywords \\"abc def ghi jkl mno pqr\\" --mode create --owner TestOwner --repository test-repository --skip-github-api true --skip-install true --skip-removal true --title \\"Test Title\\""', + ); + }); }); diff --git a/src/shared/options/augmentOptionsWithExcludes.test.ts b/src/shared/options/augmentOptionsWithExcludes.test.ts index 9772fcf05..e5a280167 100644 --- a/src/shared/options/augmentOptionsWithExcludes.test.ts +++ b/src/shared/options/augmentOptionsWithExcludes.test.ts @@ -125,6 +125,6 @@ describe("augmentOptionsWithExcludes", () => { const actual = await augmentOptionsWithExcludes(options); - expect(actual).toBe(options); + expect(actual).toStrictEqual(options); }); }); From fb07b240854cc44b61d0c381bba0ae5267bc8c78 Mon Sep 17 00:00:00 2001 From: Graham Vasquez Date: Sat, 28 Oct 2023 08:54:20 -0700 Subject: [PATCH 3/5] add falsey to cspell words --- cspell.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cspell.json b/cspell.json index 386ca4223..c74f38c6d 100644 --- a/cspell.json +++ b/cspell.json @@ -34,6 +34,7 @@ "tsup", "Unstaged", "vitest", - "wontfix" + "wontfix", + "falsey" ] } From 6e8e08d31c3d61fab564ce69abba7c4163054287 Mon Sep 17 00:00:00 2001 From: Graham Vasquez Date: Mon, 30 Oct 2023 14:22:20 -0400 Subject: [PATCH 4/5] refactor unit tests, comment updates --- cspell.json | 3 +-- src/create/createRerunSuggestion.test.ts | 13 ++++++++----- src/create/createRerunSuggestion.ts | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/cspell.json b/cspell.json index c74f38c6d..386ca4223 100644 --- a/cspell.json +++ b/cspell.json @@ -34,7 +34,6 @@ "tsup", "Unstaged", "vitest", - "wontfix", - "falsey" + "wontfix" ] } diff --git a/src/create/createRerunSuggestion.test.ts b/src/create/createRerunSuggestion.test.ts index 556685671..1347e015e 100644 --- a/src/create/createRerunSuggestion.test.ts +++ b/src/create/createRerunSuggestion.test.ts @@ -42,6 +42,11 @@ const options = { title: "Test Title", } satisfies Options; +const opts = { + ...options, + excludeLintKnip: undefined, +}; + describe("createRerunSuggestion", () => { it("includes key-value pairs with mixed truthy and falsy values", () => { const actual = createRerunSuggestion(options); @@ -95,11 +100,7 @@ describe("createRerunSuggestion", () => { ); }); - it("does not list all excludes when using common or minimum base", () => { - const opts = { - ...options, - excludeLintKnip: undefined, - }; + it("does not list all excludes when using common base", () => { const common = createRerunSuggestion({ ...opts, base: "common", @@ -109,7 +110,9 @@ describe("createRerunSuggestion", () => { expect(common).toMatchInlineSnapshot( '"npx create-typescript-app --mode create --base common --access public --author TestAuthor --description \\"Test description.\\" --directory . --email-github github@email.com --email-npm npm@email.com --exclude-all-contributors true --keywords \\"abc def ghi jkl mno pqr\\" --mode create --owner TestOwner --repository test-repository --skip-github-api true --skip-install true --skip-removal true --title \\"Test Title\\""', ); + }); + it("does not list all excludes when using minimum base", () => { const minimum = createRerunSuggestion({ ...opts, base: "minimum", diff --git a/src/create/createRerunSuggestion.ts b/src/create/createRerunSuggestion.ts index 4ab1c9843..6bd393c2c 100644 --- a/src/create/createRerunSuggestion.ts +++ b/src/create/createRerunSuggestion.ts @@ -34,11 +34,11 @@ export function createRerunSuggestion(options: Partial): string { }; const args = Object.entries(optionsNormalized) - // Sort so the base is first, then the rest are compared using the `localeCompare` string method + // Sort so the base is first, then the rest are sorted alphabetically .sort(([a], [b]) => a === "base" ? -1 : b === "base" ? 1 : a.localeCompare(b), ) - // Filter out all entries that have a key in the excluded object or have a falsey value + // Filter out all entries that have a key in the excluded object or have a falsy value .filter( ([key, value]) => getExclusions(options, optionsNormalized.base)[key as ExclusionKey] == From 9d9f6bd0b48a818d328ba9a259335b8a9286cbad Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 9 Nov 2023 12:08:49 +0000 Subject: [PATCH 5/5] inline opts variable --- src/create/createRerunSuggestion.test.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/create/createRerunSuggestion.test.ts b/src/create/createRerunSuggestion.test.ts index 1347e015e..a3e828918 100644 --- a/src/create/createRerunSuggestion.test.ts +++ b/src/create/createRerunSuggestion.test.ts @@ -42,11 +42,6 @@ const options = { title: "Test Title", } satisfies Options; -const opts = { - ...options, - excludeLintKnip: undefined, -}; - describe("createRerunSuggestion", () => { it("includes key-value pairs with mixed truthy and falsy values", () => { const actual = createRerunSuggestion(options); @@ -102,25 +97,25 @@ describe("createRerunSuggestion", () => { it("does not list all excludes when using common base", () => { const common = createRerunSuggestion({ - ...opts, base: "common", ...getExclusions(options, "common"), + excludeLintKnip: undefined, }); expect(common).toMatchInlineSnapshot( - '"npx create-typescript-app --mode create --base common --access public --author TestAuthor --description \\"Test description.\\" --directory . --email-github github@email.com --email-npm npm@email.com --exclude-all-contributors true --keywords \\"abc def ghi jkl mno pqr\\" --mode create --owner TestOwner --repository test-repository --skip-github-api true --skip-install true --skip-removal true --title \\"Test Title\\""', + '"npx create-typescript-app --mode undefined --base common"', ); }); it("does not list all excludes when using minimum base", () => { const minimum = createRerunSuggestion({ - ...opts, base: "minimum", ...getExclusions(options, "minimum"), + excludeLintKnip: undefined, }); expect(minimum).toMatchInlineSnapshot( - '"npx create-typescript-app --mode create --base minimum --access public --author TestAuthor --description \\"Test description.\\" --directory . --email-github github@email.com --email-npm npm@email.com --keywords \\"abc def ghi jkl mno pqr\\" --mode create --owner TestOwner --repository test-repository --skip-github-api true --skip-install true --skip-removal true --title \\"Test Title\\""', + '"npx create-typescript-app --mode undefined --base minimum"', ); }); });