Repository: JoshuaKGoldberg/create-typescript-app (ts)

Issue:
🚀 Feature: Allow overriding Knip entry
### Feature Request Checklist

- [x] I have pulled the latest `main` branch of the repository.
- [x] I have [searched for related issues](https://github.com/JoshuaKGoldberg/create-typescript-app/issues?q=is%3Aissue) and found none that matched my issue.

### Overview

Repos may need to customize their `knip.json` on top of what `blockKnip` currently allows. For example, https://github.com/JoshuaKGoldberg/refined-saved-replies switches its `entry` to `src/content-script.ts` rather than `index.ts`.

I'll make `entry` an Addon.

### Additional Info

🎁 

Pull request description:
feat: switch Knip entry and project to Addons
## PR Checklist

- [x] Addresses an existing open issue: fixes #2147
- [x] That issue was marked as [`status: accepting prs`](https://github.com/JoshuaKGoldberg/create-typescript-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22status%3A+accepting+prs%22)
- [x] Steps in [CONTRIBUTING.md](https://github.com/JoshuaKGoldberg/create-typescript-app/blob/main/.github/CONTRIBUTING.md) were taken

## Overview

Goes a bit beyond #2147's original intended scope of `entry` by also making `project` an Addon. This way, `blockTypeScript` and `blockVitest` fully communicate all file globs to `blockKnip`.

Also expands `blockKnip`'s `intake` to read both of those new Addon properties. This will allow customizations such as https://github.com/JoshuaKGoldberg/refined-saved-replies's `entry: ["src/content-script.ts"]` to be inferred.

🎁 

Patch:
diff --git a/knip.json b/knip.json
index 3394d6c..03b0dc0 100644
--- a/knip.json
+++ b/knip.json
@@ -1,6 +1,6 @@
 {
 	"$schema": "https://unpkg.com/knip@5.46.0/schema.json",
-	"entry": ["src/index.ts", "src/**/*.test.*"],
+	"entry": ["src/**/*.test.*", "src/index.ts"],
 	"ignoreDependencies": [
 		"all-contributors-cli",
 		"cspell-populate-words",
diff --git a/src/blocks/blockKnip.ts b/src/blocks/blockKnip.ts
index 2fbda8c..14a8c7b 100644
--- a/src/blocks/blockKnip.ts
+++ b/src/blocks/blockKnip.ts
@@ -1,3 +1,4 @@
+import removeUndefinedObjects from "remove-undefined-objects";
 import { z } from "zod";
 
 import { base } from "../base.js";
@@ -12,29 +13,32 @@ import { blockRemoveFiles } from "./blockRemoveFiles.js";
 import { blockRemoveWorkflows } from "./blockRemoveWorkflows.js";
 import { intakeFileAsJson } from "./intake/intakeFileAsJson.js";
 
-const zIgnoreDependencies = z.array(z.string());
+const zStringArray = z.array(z.string());
 
 export const blockKnip = base.createBlock({
 	about: {
 		name: "Knip",
 	},
 	addons: {
-		ignoreDependencies: zIgnoreDependencies.optional(),
+		entry: zStringArray.optional(),
+		ignoreDependencies: zStringArray.optional(),
+		project: zStringArray.optional(),
 	},
 	intake({ files }) {
 		const knipJson = intakeFileAsJson(files, ["knip.json"]);
-		if (!knipJson?.ignoreDependencies) {
+		if (!knipJson) {
 			return undefined;
 		}
 
-		return {
-			ignoreDependencies: zIgnoreDependencies.safeParse(
-				knipJson.ignoreDependencies,
-			).data,
-		};
+		return removeUndefinedObjects({
+			entry: zStringArray.safeParse(knipJson.entry).data,
+			ignoreDependencies: zStringArray.safeParse(knipJson.ignoreDependencies)
+				.data,
+			project: zStringArray.safeParse(knipJson.project).data,
+		});
 	},
 	produce({ addons }) {
-		const { ignoreDependencies } = addons;
+		const { entry, ignoreDependencies, project } = addons;
 		return {
 			addons: [
 				blockDevelopmentDocs({
@@ -68,13 +72,13 @@ export const blockKnip = base.createBlock({
 			files: {
 				"knip.json": JSON.stringify({
 					$schema: `https://unpkg.com/knip@${getPackageDependency("knip")}/schema.json`,
-					entry: ["src/index.ts", "src/**/*.test.*"],
+					entry: entry?.sort(),
 					ignoreDependencies,
 					ignoreExportsUsedInFile: {
 						interface: true,
 						type: true,
 					},
-					project: ["src/**/*.ts"],
+					project: project?.sort(),
 				}),
 			},
 		};
diff --git a/src/blocks/blockTypeScript.ts b/src/blocks/blockTypeScript.ts
index b4ceb38..195c159 100644
--- a/src/blocks/blockTypeScript.ts
+++ b/src/blocks/blockTypeScript.ts
@@ -8,6 +8,7 @@ import { blockDevelopmentDocs } from "./blockDevelopmentDocs.js";
 import { blockExampleFiles } from "./blockExampleFiles.js";
 import { blockGitHubActionsCI } from "./blockGitHubActionsCI.js";
 import { blockGitignore } from "./blockGitignore.js";
+import { blockKnip } from "./blockKnip.js";
 import { blockMarkdownlint } from "./blockMarkdownlint.js";
 import { blockPackageJson } from "./blockPackageJson.js";
 import { blockRemoveWorkflows } from "./blockRemoveWorkflows.js";
@@ -81,6 +82,10 @@ export * from "./types.js";
 				blockGitHubActionsCI({
 					jobs: [{ name: "Type Check", steps: [{ run: "pnpm tsc" }] }],
 				}),
+				blockKnip({
+					entry: ["src/index.ts"],
+					project: ["src/**/*.ts"],
+				}),
 				blockMarkdownlint({
 					ignores: ["lib/"],
 				}),


Test patch:
diff --git a/src/blocks/blockKnip.test.ts b/src/blocks/blockKnip.test.ts
index 830e804..34228bd 100644
--- a/src/blocks/blockKnip.test.ts
+++ b/src/blocks/blockKnip.test.ts
@@ -61,7 +61,7 @@ describe("blockKnip", () => {
 			    },
 			  ],
 			  "files": {
-			    "knip.json": "{"$schema":"https://unpkg.com/knip@5.46.0/schema.json","entry":["src/index.ts","src/**/*.test.*"],"ignoreExportsUsedInFile":{"interface":true,"type":true},"project":["src/**/*.ts"]}",
+			    "knip.json": "{"$schema":"https://unpkg.com/knip@5.46.0/schema.json","ignoreExportsUsedInFile":{"interface":true,"type":true}}",
 			  },
 			}
 		`);
@@ -70,7 +70,9 @@ describe("blockKnip", () => {
 	test("with addons", () => {
 		const creation = testBlock(blockKnip, {
 			addons: {
+				entry: ["src/index.ts"],
 				ignoreDependencies: ["abc", "def"],
+				project: ["src/**/*.ts"],
 			},
 			options: optionsBase,
 		});
@@ -122,7 +124,7 @@ describe("blockKnip", () => {
 			    },
 			  ],
 			  "files": {
-			    "knip.json": "{"$schema":"https://unpkg.com/knip@5.46.0/schema.json","entry":["src/index.ts","src/**/*.test.*"],"ignoreDependencies":["abc","def"],"ignoreExportsUsedInFile":{"interface":true,"type":true},"project":["src/**/*.ts"]}",
+			    "knip.json": "{"$schema":"https://unpkg.com/knip@5.46.0/schema.json","entry":["src/index.ts"],"ignoreDependencies":["abc","def"],"ignoreExportsUsedInFile":{"interface":true,"type":true},"project":["src/**/*.ts"]}",
 			  },
 			}
 		`);
@@ -201,7 +203,7 @@ describe("blockKnip", () => {
 			    },
 			  ],
 			  "files": {
-			    "knip.json": "{"$schema":"https://unpkg.com/knip@5.46.0/schema.json","entry":["src/index.ts","src/**/*.test.*"],"ignoreExportsUsedInFile":{"interface":true,"type":true},"project":["src/**/*.ts"]}",
+			    "knip.json": "{"$schema":"https://unpkg.com/knip@5.46.0/schema.json","ignoreExportsUsedInFile":{"interface":true,"type":true}}",
 			  },
 			}
 		`);
diff --git a/src/blocks/blockTypeScript.test.ts b/src/blocks/blockTypeScript.test.ts
index f5ded81..c9fae0f 100644
--- a/src/blocks/blockTypeScript.test.ts
+++ b/src/blocks/blockTypeScript.test.ts
@@ -90,6 +90,17 @@ describe("blockTypeScript", () => {
 			      },
 			      "block": [Function],
 			    },
+			    {
+			      "addons": {
+			        "entry": [
+			          "src/index.ts",
+			        ],
+			        "project": [
+			          "src/**/*.ts",
+			        ],
+			      },
+			      "block": [Function],
+			    },
 			    {
 			      "addons": {
 			        "ignores": [
@@ -242,6 +253,17 @@ describe("blockTypeScript", () => {
 			      },
 			      "block": [Function],
 			    },
+			    {
+			      "addons": {
+			        "entry": [
+			          "src/index.ts",
+			        ],
+			        "project": [
+			          "src/**/*.ts",
+			        ],
+			      },
+			      "block": [Function],
+			    },
 			    {
 			      "addons": {
 			        "ignores": [
@@ -392,6 +414,17 @@ describe("blockTypeScript", () => {
 			      },
 			      "block": [Function],
 			    },
+			    {
+			      "addons": {
+			        "entry": [
+			          "src/index.ts",
+			        ],
+			        "project": [
+			          "src/**/*.ts",
+			        ],
+			      },
+			      "block": [Function],
+			    },
 			    {
 			      "addons": {
 			        "ignores": [
@@ -551,6 +584,17 @@ describe("blockTypeScript", () => {
 			      },
 			      "block": [Function],
 			    },
+			    {
+			      "addons": {
+			        "entry": [
+			          "src/index.ts",
+			        ],
+			        "project": [
+			          "src/**/*.ts",
+			        ],
+			      },
+			      "block": [Function],
+			    },
 			    {
 			      "addons": {
 			        "ignores": [
diff --git a/src/blocks/blockVitest.test.ts b/src/blocks/blockVitest.test.ts
index 0955da1..ad6fdcf 100644
--- a/src/blocks/blockVitest.test.ts
+++ b/src/blocks/blockVitest.test.ts
@@ -165,6 +165,14 @@ describe("blockVitest", () => {
 			      },
 			      "block": [Function],
 			    },
+			    {
+			      "addons": {
+			        "entry": [
+			          "src/**/*.test.*",
+			        ],
+			      },
+			      "block": [Function],
+			    },
 			    {
 			      "addons": {
 			        "properties": {
@@ -403,6 +411,14 @@ describe("blockVitest", () => {
 			      },
 			      "block": [Function],
 			    },
+			    {
+			      "addons": {
+			        "entry": [
+			          "src/**/*.test.*",
+			        ],
+			      },
+			      "block": [Function],
+			    },
 			    {
 			      "addons": {
 			        "properties": {
@@ -679,6 +695,14 @@ describe("blockVitest", () => {
 			      },
 			      "block": [Function],
 			    },
+			    {
+			      "addons": {
+			        "entry": [
+			          "src/**/*.test.*",
+			        ],
+			      },
+			      "block": [Function],
+			    },
 			    {
 			      "addons": {
 			        "properties": {
@@ -926,6 +950,14 @@ describe("blockVitest", () => {
 			      },
 			      "block": [Function],
 			    },
+			    {
+			      "addons": {
+			        "entry": [
+			          "src/**/*.test.*",
+			        ],
+			      },
+			      "block": [Function],
+			    },
 			    {
 			      "addons": {
 			        "properties": {
diff --git a/src/blocks/blockVitest.ts b/src/blocks/blockVitest.ts
index 7091719..db5bade 100644
--- a/src/blocks/blockVitest.ts
+++ b/src/blocks/blockVitest.ts
@@ -9,6 +9,7 @@ import { blockESLint } from "./blockESLint.js";
 import { blockExampleFiles } from "./blockExampleFiles.js";
 import { blockGitHubActionsCI, zActionStep } from "./blockGitHubActionsCI.js";
 import { blockGitignore } from "./blockGitignore.js";
+import { blockKnip } from "./blockKnip.js";
 import { blockPackageJson } from "./blockPackageJson.js";
 import { blockPrettier } from "./blockPrettier.js";
 import { blockRemoveDependencies } from "./blockRemoveDependencies.js";
@@ -193,6 +194,9 @@ describe(greet, () => {
 						},
 					],
 				}),
+				blockKnip({
+					entry: ["src/**/*.test.*"],
+				}),
 				blockPackageJson({
 					properties: {
 						devDependencies: getPackageDependencies(