From 2a4cc963da5b949e0e2c43c76f7cbd05616f9874 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 3 Jan 2024 14:37:16 -0500 Subject: [PATCH 1/6] chore: overhaul and re-document end-to-end tests --- .github/DEVELOPMENT.md | 36 +++++++++++++++++++++++++++++++++-- script/create-test-e2e.js | 3 +++ script/initialize-test-e2e.js | 14 +++++++++----- script/migrate-test-e2e.js | 20 +++++++++---------- 4 files changed, 55 insertions(+), 18 deletions(-) diff --git a/.github/DEVELOPMENT.md b/.github/DEVELOPMENT.md index d85b4859d..255a5a526 100644 --- a/.github/DEVELOPMENT.md +++ b/.github/DEVELOPMENT.md @@ -210,5 +210,37 @@ The `pnpm run test:migrate` script is run in CI to ensure that templating change See `.github/workflows/test-migrate.yml`. > Tip: if the migration test is failing in CI and you don't see any errors, try [downloading the full logs](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/using-workflow-run-logs#downloading-logs). -> There'll likely be a list of changed files under a message like _`Oh no! Running the migrate script modified some files:`_. -> You can also try running the test script locally. + +##### Migration Snapshot Failures + +The migration test uses the [Vitest file snapshot](https://vitest.dev/guide/snapshot#file-snapshots) in `script/__snapshots__/migrate-test-e2e.js.snap` to store expected differences to this repository after running the migration script. +The end-to-end migration test will fail any changes that don't keep the same differences in that snapshot. + +You can update the snapshot file by: + +1. Committing any changes to your local repository +2. Running `pnpm i` and `pnpm build` if any updates have been made to the `package.json` or `src/` files, respectively +3. Running `pnpm run test:migrate -u` to update the snapshot + +At this point there will be some files changed: + +- `script/__snapshots__/migrate-test-e2e.js.snap` will have updates if any files mismatched templates +- The actual updated files on disk will be there too + +If the snapshot file changes are what you expected, then you can commit them. +The rest of the file changes can be reverted. + +> [🚀 Feature: Add a way to apply known file changes after migration #1184](https://github.com/JoshuaKGoldberg/create-typescript-app/issues/1184) tracks turning the test snapshot into a feature. + +##### Unexpected File Modifications + +The migration test also asserts that no files were unexpectedly changed. +If you see a failure like: + +```plaintext +Oh no! Running the migrate script unexpectedly modified: + - ... +``` + +...then that means the file generated from templates differs from what's checked into the repository. +This is most often caused by changes to templates not being applied to checked-in files too. diff --git a/script/create-test-e2e.js b/script/create-test-e2e.js index 7a6092cd1..0f41aa0e9 100644 --- a/script/create-test-e2e.js +++ b/script/create-test-e2e.js @@ -10,6 +10,8 @@ const title = "Test Title"; await $`rm -rf ${repository}`; +// Fist we run with --mode create to create a new new local repository, +// asserting that pnpm i passes in that repository's directory. await $({ stdio: "inherit", })`c8 -o ./coverage-create -r html -r lcov --src src node ./bin/index.js --base everything --mode create --author ${author} --email ${email} --description ${description} --owner ${owner} --title ${title} --repository ${repository} --skip-all-contributors-api --skip-github-api`; @@ -18,6 +20,7 @@ process.chdir(repository); const failures = []; +// Then we run each of the CI commands to assert that they pass too. for (const command of [ `pnpm i`, `pnpm run build`, diff --git a/script/initialize-test-e2e.js b/script/initialize-test-e2e.js index e866e7e11..4db91d8fa 100644 --- a/script/initialize-test-e2e.js +++ b/script/initialize-test-e2e.js @@ -8,10 +8,11 @@ const owner = "RNR1"; const title = "New Title Test"; const repository = "new-repository-test"; -// First we run initialize to modifies the local repo, so we can test the changes +// Fist we run with --mode initialize to modify the local repository files, +// asserting that the created package.json keeps the general description. await $({ stdio: "inherit", -})`node ./bin/index.js --description ${description} --base everything --mode initialize --owner ${owner} --title ${title} --repository ${repository} --skip-all-contributors-api --skip-github-api --skip-restore`; +})`pnpm run initialize --base everything --mode initialize --description ${description} --owner ${owner} --title ${title} --repository ${repository} --skip-all-contributors-api --skip-github-api --skip-restore`; const newPackageJson = JSON.parse( (await fs.readFile("./package.json")).toString(), @@ -21,6 +22,8 @@ console.log("New package JSON:", newPackageJson); assert.equal(newPackageJson.description, description); assert.equal(newPackageJson.name, repository); +// Assert that the initialize script used the provided values in files, +// except for the 'This package was templated with ...' attribution notice. const files = await globby(["*.*", "**/*.*"], { gitignore: true, ignoreFiles: ["script/initialize-test-e2e.js"], @@ -34,11 +37,12 @@ for (const search of [`/JoshuaKGoldberg/`, "create-typescript-app"]) { ); } +// Use Knip to assert that none of the template-only dependencies remain. +// They should have been removed as part of initialization. try { await $`pnpm run lint:knip`; } catch (error) { - console.error("Error running lint:knip:", error); - process.exitCode = 1; + throw new Error("Error running lint:knip:", { cause: error }); } // Now that initialize has passed normal steps, we reset everything, @@ -49,4 +53,4 @@ await $`pnpm i`; await $`pnpm run build`; await $({ stdio: "inherit", -})`c8 -o ./coverage -r html -r lcov --src src node ./bin/index.js --base everything --description ${description} --mode initialize --owner ${owner} --title ${title} --repository ${repository} --skip-all-contributors-api --skip-github-api --skip-removal --skip-restore`; +})`c8 -o ./coverage -r html -r lcov --src src node ./bin/index.js --base everything --mode initialize --description ${description}--owner ${owner} --title ${title} --repository ${repository} --skip-all-contributors-api --skip-github-api --skip-removal --skip-restore`; diff --git a/script/migrate-test-e2e.js b/script/migrate-test-e2e.js index d528e60cb..fed3914fd 100644 --- a/script/migrate-test-e2e.js +++ b/script/migrate-test-e2e.js @@ -120,6 +120,8 @@ describe("expected file changes", () => { `Looks like there were no changes to ${file} from migration?`, ); + // If this fails, see .github/DEVELOPMENT.md > Setup Scripts for context. + // Then see .github/DEVELOPMENT.md > Migration Snapshot Failures. expect(contentsAfterGitMarkers).toMatchSnapshot(); }); }); @@ -149,22 +151,18 @@ test("unexpected file changes", async () => { const gitDiffCommand = `git diff HEAD -- ${unstagedModifiedFiles.join( " ", )}`; - console.log( - `Stdout from running \`${gitDiffCommand}\`:\n${ - (await execaCommand(gitDiffCommand)).stdout - }`, - ); + const { stdout } = await execaCommand(gitDiffCommand); + + console.log(`Stdout from running \`${gitDiffCommand}\`:\n${stdout}`); + throw new Error( [ "", - "Oh no! Running the migrate script modified some files:", + "Oh no! Running the migrate script unexpectedly modified:", ...unstagedModifiedFiles.map((filePath) => ` - ${filePath}`), "", - "That likely indicates changes made to the repository without", - "corresponding updates to templates in src/.", - "", - "Please search for those file(s)' name(s) under src/migrate for", - "the corresponding template and update those as well.", + "See .github/DEVELOPMENT.md > Setup Scripts for context.", + "Then see .github/DEVELOPMENT.md > Unexpected File Modifications.", ] .map((line) => chalk.red(line)) .join("\n"), From 231fdcf0538d8d18429cf00debd4ebce9348e82a Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 3 Jan 2024 16:40:11 -0500 Subject: [PATCH 2/6] fix: spacing... --- script/initialize-test-e2e.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/initialize-test-e2e.js b/script/initialize-test-e2e.js index 4db91d8fa..d0e0e7e91 100644 --- a/script/initialize-test-e2e.js +++ b/script/initialize-test-e2e.js @@ -53,4 +53,4 @@ await $`pnpm i`; await $`pnpm run build`; await $({ stdio: "inherit", -})`c8 -o ./coverage -r html -r lcov --src src node ./bin/index.js --base everything --mode initialize --description ${description}--owner ${owner} --title ${title} --repository ${repository} --skip-all-contributors-api --skip-github-api --skip-removal --skip-restore`; +})`c8 -o ./coverage -r html -r lcov --src src node ./bin/index.js --base everything --mode initialize --description ${description} --owner ${owner} --title ${title} --repository ${repository} --skip-all-contributors-api --skip-github-api --skip-removal --skip-restore`; From 0ade9cb4bd25833cd4f9300ebd3a0526536d9771 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 3 Jan 2024 17:03:18 -0500 Subject: [PATCH 3/6] Also mention auto-fixers --- .github/DEVELOPMENT.md | 6 ++++++ docs/Creation.md | 12 ++++++++++-- docs/Initialization.md | 4 ++-- docs/Migration.md | 40 +++++++++++++++++++++++++++++++++++++--- docs/Options.md | 4 ++-- 5 files changed, 57 insertions(+), 9 deletions(-) diff --git a/.github/DEVELOPMENT.md b/.github/DEVELOPMENT.md index 255a5a526..136547e91 100644 --- a/.github/DEVELOPMENT.md +++ b/.github/DEVELOPMENT.md @@ -119,6 +119,8 @@ Each follows roughly the same general flow: ### The Creation Script +> 📝 See [`docs/Creation.md`](../docs/Creation.md) for user documentation on the creation script. + This template's "creation" script is located in `src/create/`. You can run it locally with `node bin/index.js --mode create`. Note that files need to be built with `pnpm run build` beforehand. @@ -142,6 +144,8 @@ See `.github/workflows/test-create.yml`. ### The Initialization Script +> 📝 See [`docs/Initialization.md`](../docs/Initialization.md) for user documentation on the initialization script. + This template's "initialization" script is located in `src/initialize/`. You can run it locally with `pnpm run initialize`. It uses [`tsx`](https://github.com/esbuild-kit/tsx) so you don't need to build files before running. @@ -172,6 +176,8 @@ See `.github/workflows/test-initialize.yml`. ### The Migration Script +> 📝 See [`docs/Migration.md`](../docs/Migration.md) for user documentation on the migration script. + This template's "migration" script is located in `src/migrate/`. Note that files need to be built with `pnpm run build` beforehand. diff --git a/docs/Creation.md b/docs/Creation.md index 15d8be8ae..5572d9d15 100644 --- a/docs/Creation.md +++ b/docs/Creation.md @@ -6,7 +6,15 @@ You can run `npx create-typescript-app` in your terminal to interactively create npx create-typescript-app ``` -Then, go through the following two steps to set up required repository tooling on GitHub: +The creation script will by default: + +1. Create a new directory with the given repository name +2. Initialize that new directory as a local Git repository +3. Copy the template's files to that directory +4. Create a new repository on GitHub and set it as the local repository's upstream +5. Configure relevant settings on the GitHub repository + +You'll then need to manually go through the following two steps to set up tooling on GitHub: 1. Create two tokens in [repository secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets) _(unless you chose to opt out of releases)_: - `ACCESS_TOKEN`: A [GitHub PAT](https://github.com/settings/tokens/new) with _repo_ and _workflow_ permissions @@ -23,7 +31,7 @@ Hooray! 🥳 You can explicitly provide some or all of the options the script would prompt for as command-line flags. See [Options.md](./Options.md). -For example, running the creation script and skipping all GitHub APIs: +For example, running the creation script and skipping all GitHub-related APIs: ```shell npx create-typescript-app --mode create --skip-all-contributors-api --skip-github-api diff --git a/docs/Initialization.md b/docs/Initialization.md index 4512f609c..f2f17d3f7 100644 --- a/docs/Initialization.md +++ b/docs/Initialization.md @@ -18,7 +18,7 @@ It will then remove itself and uninstall dependencies only used for initializati pnpm run initialize ``` -Then, go through the following two steps to set up required repository tooling on GitHub: +You'll then need to manually go through the following two steps to set up tooling on GitHub: 1. Create two tokens in [repository secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets) _(unless you chose to opt out of releases)_: - `ACCESS_TOKEN`: A [GitHub PAT](https://github.com/settings/tokens/new) with _repo_ and _workflow_ permissions @@ -37,7 +37,7 @@ See [Options.md](./Options.md). `pnpm run initialize` will set `--mode` to `initialize`. -For example, running the initialization script and skipping all GitHub APIs: +For example, running the initialization script and skipping all GitHub-related APIs: ```shell pnpm run initialize --skip-all-contributors-api --skip-github-api diff --git a/docs/Migration.md b/docs/Migration.md index 0c2b006a4..e1a16b399 100644 --- a/docs/Migration.md +++ b/docs/Migration.md @@ -6,6 +6,33 @@ If you have an existing repository that you'd like to give the files from this r npx create-typescript-app ``` +The migration script will: + +- Uninstall any known old packages that conflict with this template's tooling +- Delete configuration files used with those old packages +- Install any packages needed for this template's tooling +- Create or rewrite configuration files for the new tooling +- Run ESLint and Prettier auto-fixers to align formatting and style to the new settings + +For example, if the repository previously using Jest for testing: + +- `eslint-plugin-jest`, `jest`, and other Jest-related packages will be uninstalled +- Any Jest config file like `jest.config.js` will be deleted +- `eslint-plugin-vitest`, `vitest`, and other Vitest-related packages will be installed +- A `vitest.config.ts` file will be created + +You'll then need to manually go through the following two steps to set up tooling on GitHub: + +1. Create two tokens in [repository secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets) _(unless you chose to opt out of releases)_: + - `ACCESS_TOKEN`: A [GitHub PAT](https://github.com/settings/tokens/new) with _repo_ and _workflow_ permissions + - `NPM_TOKEN`: An [npm access token](https://docs.npmjs.com/creating-and-viewing-access-tokens/) with _Automation_ permissions +2. Install two GitHub apps: + - [Codecov](https://github.com/marketplace/codecov) _(unless you chose to opt out of tests)_ + - [Renovate](https://github.com/marketplace/renovate) _(unless you chose to opt out of renovate)_ + +Your repository will then have an approximate copy of this template's tooling ready for you to review! +Hooray! 🥳 + > [!WARNING] > Migration will override many files in your repository. > You'll want to review each of the changes. @@ -13,13 +40,20 @@ npx create-typescript-app ## Options -You can explicitly provide some or all of the options the script would prompt for as command-line flags. +`create-typescript-app` will detect if it's in an existing repository. +It also allows specifying `--mode migrate` if that detection misinterprets the current directory: + +```shell +npx create-typescript-app --mode migrate +``` + +Additionally, you can explicitly provide some or all of the options the script would prompt for as command-line flags. See [Options.md](./Options.md). -For example, running the migration script and skipping all GitHub APIs: +For example, running the migration script and skipping all GitHub-related APIs: ```shell -npx create-typescript-app --mode migrate --skip-all-contributors-api --skip-github-api +npx create-typescript-app --skip-all-contributors-api --skip-github-api ``` See [Tooling.md](./Tooling.md) for details on the tooling pieces and which bases they're included in. diff --git a/docs/Options.md b/docs/Options.md index 40e69d8e1..28793ebdd 100644 --- a/docs/Options.md +++ b/docs/Options.md @@ -13,8 +13,8 @@ The following required options will be prompted for interactively if not provide These required options determine how the creation script will set up and scaffold the repository: - `--base`: Whether to scaffold the repository with: - - `minimum`: Just the bare starter tooling most repositories should ideally include. - - `common`: Important additions to the minimum starters such as releases and tests. + - `minimum`: Just the bare starter tooling most repositories should ideally include + - `common`: Important additions to the minimum starters such as releases and tests - `everything`: The most thorough tooling imaginable: sorting, spellchecking, and more! - `prompt`: Fine-grained control over which tooling pieces to use - `--mode`: Whether to: From 08c316896e62b1085072c432fbc991ee6a2a623b Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 3 Jan 2024 17:03:55 -0500 Subject: [PATCH 4/6] Nitpicking phrasing --- docs/Migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Migration.md b/docs/Migration.md index e1a16b399..63f7fe80a 100644 --- a/docs/Migration.md +++ b/docs/Migration.md @@ -40,7 +40,7 @@ Hooray! 🥳 ## Options -`create-typescript-app` will detect if it's in an existing repository. +`create-typescript-app` will detect whether it's being run in an existing repository. It also allows specifying `--mode migrate` if that detection misinterprets the current directory: ```shell From f69ccbdc4745ae7ec1345dee800418f7a67402b8 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 3 Jan 2024 17:04:06 -0500 Subject: [PATCH 5/6] Nitpicking phrasing --- docs/Migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Migration.md b/docs/Migration.md index 63f7fe80a..262f7cb12 100644 --- a/docs/Migration.md +++ b/docs/Migration.md @@ -47,7 +47,7 @@ It also allows specifying `--mode migrate` if that detection misinterprets the c npx create-typescript-app --mode migrate ``` -Additionally, you can explicitly provide some or all of the options the script would prompt for as command-line flags. +You can explicitly provide some or all of the options the script would prompt for as command-line flags. See [Options.md](./Options.md). For example, running the migration script and skipping all GitHub-related APIs: From e5e41942313ae9a4cb71b000abc5dbc5368a8018 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 4 Jan 2024 13:05:51 -0500 Subject: [PATCH 6/6] Split out a few files and added more descriptions --- .github/DEVELOPMENT.md | 12 ++++++ .../creation/createDotESLintignore.test.ts | 30 +++++++++++++ .../writing/creation/createDotESLintignore.ts | 14 ++++++ .../creation/createDotGitignore.test.ts | 26 +++++++++++ .../writing/creation/createDotGitignore.ts | 10 +++++ .../writing/creation/createTsupConfig.test.ts | 43 +++++++++++++++++++ .../writing/creation/createTsupConfig.ts | 17 ++++++++ src/steps/writing/creation/rootFiles.ts | 34 +++------------ 8 files changed, 158 insertions(+), 28 deletions(-) create mode 100644 src/steps/writing/creation/createDotESLintignore.test.ts create mode 100644 src/steps/writing/creation/createDotESLintignore.ts create mode 100644 src/steps/writing/creation/createDotGitignore.test.ts create mode 100644 src/steps/writing/creation/createDotGitignore.ts create mode 100644 src/steps/writing/creation/createTsupConfig.test.ts create mode 100644 src/steps/writing/creation/createTsupConfig.ts diff --git a/.github/DEVELOPMENT.md b/.github/DEVELOPMENT.md index 136547e91..d0d240164 100644 --- a/.github/DEVELOPMENT.md +++ b/.github/DEVELOPMENT.md @@ -200,6 +200,9 @@ node ../create-typescript-app/bin/migrate.js #### Testing the Migration Script +> 💡 Seeing `Oh no! Running the migrate script unexpectedly modified:` errors? +> _[Unexpected File Modifications](#unexpected-file-modifications)_ covers that below. + You can run the end-to-end test for migrating locally on the command-line: ```shell @@ -250,3 +253,12 @@ Oh no! Running the migrate script unexpectedly modified: ...then that means the file generated from templates differs from what's checked into the repository. This is most often caused by changes to templates not being applied to checked-in files too. + +Templates for files are generally stored in [`src/steps/writing/creation`] under a path roughly corresponding to the file they describe. +For example, the template for `tsup.config.ts` is stored in [`src/steps/writing/creation/createTsupConfig.ts`](../src/steps/writing/creation/createTsupConfig.ts). +If the `createTsupConfig` function were to be modified without an equivalent change to `tsup.config.ts` -or vice-versa- then the migration test would report: + +```plaintext +Oh no! Running the migrate script unexpectedly modified: + - tsup.config.ts +``` diff --git a/src/steps/writing/creation/createDotESLintignore.test.ts b/src/steps/writing/creation/createDotESLintignore.test.ts new file mode 100644 index 000000000..8c9fb7e2e --- /dev/null +++ b/src/steps/writing/creation/createDotESLintignore.test.ts @@ -0,0 +1,30 @@ +import { describe, expect, it } from "vitest"; + +import { createDotESLintignore } from "./createDotESLintignore.js"; + +describe("createDotESLintignore", () => { + it("creates an ignore file with coverage when excludeTests is false", () => { + const actual = createDotESLintignore({ excludeTests: false }); + + expect(actual).toMatchInlineSnapshot(` + "!.* + coverage + lib + node_modules + pnpm-lock.yaml + " + `); + }); + + it("creates an ignore file without coverage when excludeTests is true", () => { + const actual = createDotESLintignore({ excludeTests: true }); + + expect(actual).toMatchInlineSnapshot(` + "!.* + lib + node_modules + pnpm-lock.yaml + " + `); + }); +}); diff --git a/src/steps/writing/creation/createDotESLintignore.ts b/src/steps/writing/creation/createDotESLintignore.ts new file mode 100644 index 000000000..ad0d4d921 --- /dev/null +++ b/src/steps/writing/creation/createDotESLintignore.ts @@ -0,0 +1,14 @@ +import { Options } from "../../../shared/types.js"; +import { formatIgnoreFile } from "./formatters/formatIgnoreFile.js"; + +export function createDotESLintignore(options: Pick) { + return formatIgnoreFile( + [ + "!.*", + ...(options.excludeTests ? [] : ["coverage"]), + "lib", + "node_modules", + "pnpm-lock.yaml", + ].filter(Boolean), + ); +} diff --git a/src/steps/writing/creation/createDotGitignore.test.ts b/src/steps/writing/creation/createDotGitignore.test.ts new file mode 100644 index 000000000..c887e4b66 --- /dev/null +++ b/src/steps/writing/creation/createDotGitignore.test.ts @@ -0,0 +1,26 @@ +import { describe, expect, it } from "vitest"; + +import { createDotGitignore } from "./createDotGitignore.js"; + +describe("createDotGitignore", () => { + it("creates an ignore file with coverage when excludeTests is false", () => { + const actual = createDotGitignore({ excludeTests: false }); + + expect(actual).toMatchInlineSnapshot(` + "coverage/ + lib/ + node_modules/ + " + `); + }); + + it("creates an ignore file without coverage when excludeTests is true", () => { + const actual = createDotGitignore({ excludeTests: true }); + + expect(actual).toMatchInlineSnapshot(` + "lib/ + node_modules/ + " + `); + }); +}); diff --git a/src/steps/writing/creation/createDotGitignore.ts b/src/steps/writing/creation/createDotGitignore.ts new file mode 100644 index 000000000..3321ba826 --- /dev/null +++ b/src/steps/writing/creation/createDotGitignore.ts @@ -0,0 +1,10 @@ +import { Options } from "../../../shared/types.js"; +import { formatIgnoreFile } from "./formatters/formatIgnoreFile.js"; + +export function createDotGitignore(options: Pick) { + return formatIgnoreFile([ + ...(options.excludeTests ? [] : ["coverage/"]), + "lib/", + "node_modules/", + ]); +} diff --git a/src/steps/writing/creation/createTsupConfig.test.ts b/src/steps/writing/creation/createTsupConfig.test.ts new file mode 100644 index 000000000..5ee040602 --- /dev/null +++ b/src/steps/writing/creation/createTsupConfig.test.ts @@ -0,0 +1,43 @@ +import { describe, expect, it } from "vitest"; + +import { createTsupConfig } from "./createTsupConfig.js"; + +describe("createTsupConfig", () => { + it("creates an ignore file with test entries when excludeTests is false", async () => { + const actual = await createTsupConfig({ excludeTests: false }); + + expect(actual).toMatchInlineSnapshot(` + "import { defineConfig } from "tsup"; + + export default defineConfig({ + bundle: false, + clean: true, + dts: true, + entry: ["src/**/*.ts", "!src/**/*.test.*"], + format: "esm", + outDir: "lib", + sourcemap: true, + }); + " + `); + }); + + it("creates an ignore file without test entries when excludeTests is true", async () => { + const actual = await createTsupConfig({ excludeTests: true }); + + expect(actual).toMatchInlineSnapshot(` + "import { defineConfig } from "tsup"; + + export default defineConfig({ + bundle: false, + clean: true, + dts: true, + entry: ["src/**/*.ts"], + format: "esm", + outDir: "lib", + sourcemap: true, + }); + " + `); + }); +}); diff --git a/src/steps/writing/creation/createTsupConfig.ts b/src/steps/writing/creation/createTsupConfig.ts new file mode 100644 index 000000000..fdb33d57d --- /dev/null +++ b/src/steps/writing/creation/createTsupConfig.ts @@ -0,0 +1,17 @@ +import { Options } from "../../../shared/types.js"; +import { formatTypeScript } from "./formatters/formatTypeScript.js"; + +export async function createTsupConfig(options: Pick) { + return await formatTypeScript(`import { defineConfig } from "tsup"; + + export default defineConfig({ + bundle: false, + clean: true, + dts: true, + entry: ["src/**/*.ts"${options.excludeTests ? "" : `, "!src/**/*.test.*"`}], + format: "esm", + outDir: "lib", + sourcemap: true, + }); + `); +} diff --git a/src/steps/writing/creation/rootFiles.ts b/src/steps/writing/creation/rootFiles.ts index a9a016ddc..a2d002076 100644 --- a/src/steps/writing/creation/rootFiles.ts +++ b/src/steps/writing/creation/rootFiles.ts @@ -1,29 +1,19 @@ import { Options } from "../../../shared/types.js"; +import { createDotESLintignore } from "./createDotESLintignore.js"; +import { createDotGitignore } from "./createDotGitignore.js"; import { createESLintRC } from "./createESLintRC.js"; +import { createTsupConfig } from "./createTsupConfig.js"; import { formatIgnoreFile } from "./formatters/formatIgnoreFile.js"; import { formatJson } from "./formatters/formatJson.js"; -import { formatTypeScript } from "./formatters/formatTypeScript.js"; import { writeAllContributorsRC } from "./writeAllContributorsRC.js"; import { writePackageJson } from "./writePackageJson.js"; export async function createRootFiles(options: Options) { return { ".all-contributorsrc": await writeAllContributorsRC(options), - ".eslintignore": formatIgnoreFile( - [ - "!.*", - ...(options.excludeTests ? [] : ["coverage"]), - "lib", - "node_modules", - "pnpm-lock.yaml", - ].filter(Boolean), - ), + ".eslintignore": createDotESLintignore(options), ".eslintrc.cjs": await createESLintRC(options), - ".gitignore": formatIgnoreFile([ - ...(options.excludeTests ? [] : ["coverage/"]), - "lib/", - "node_modules/", - ]), + ".gitignore": createDotGitignore(options), ...(!options.excludeLintMd && { ".markdownlint.json": await formatJson({ extends: "markdownlint/style/prettier", @@ -173,19 +163,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. }, include: ["src"], }), - "tsup.config.ts": - await formatTypeScript(`import { defineConfig } from "tsup"; - - export default defineConfig({ - bundle: false, - clean: true, - dts: true, - entry: ["src/**/*.ts"${options.excludeTests ? "" : `, "!src/**/*.test.*"`}], - format: "esm", - outDir: "lib", - sourcemap: true, - }); - `), + "tsup.config.ts": await createTsupConfig(options), ...(!options.excludeTests && { "vitest.config.ts": `import { defineConfig } from "vitest/config";