Skip to content

Commit 9b1f68c

Browse files
authoredMar 28, 2025··
feat: allow customizing tsc, tsup builds (#2060)
## PR Checklist - [x] Addresses an existing open issue: fixes #2057 - [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 🎁
1 parent 3c048e6 commit 9b1f68c

6 files changed

+189
-37
lines changed
 

‎package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@
6666
"title-case": "^4.3.2",
6767
"trash-cli": "^6.0.0",
6868
"zod": "^3.24.2",
69-
"zod-package-json": "^1.1.0"
69+
"zod-package-json": "^1.1.0",
70+
"zod-tsconfig": "^0.1.1"
7071
},
7172
"devDependencies": {
7273
"@eslint-community/eslint-plugin-eslint-comments": "4.4.1",

‎pnpm-lock.yaml

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/blocks/blockTSup.test.ts

+3-24
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,7 @@ describe("blockTSup", () => {
8888
"files": {
8989
"tsup.config.ts": "import { defineConfig } from "tsup";
9090
91-
export default defineConfig({
92-
bundle: false,
93-
clean: true,
94-
dts: true,
95-
entry: ["src/**/*.ts"],
96-
format: "esm",
97-
outDir: "lib",
98-
});
91+
export default defineConfig({"bundle":false,"clean":true,"dts":true,"entry":["src/**/*.ts"],"format":"esm","outDir":"lib"});
9992
",
10093
},
10194
"scripts": undefined,
@@ -214,14 +207,7 @@ describe("blockTSup", () => {
214207
"files": {
215208
"tsup.config.ts": "import { defineConfig } from "tsup";
216209
217-
export default defineConfig({
218-
bundle: false,
219-
clean: true,
220-
dts: true,
221-
entry: ["src/**/*.ts"],
222-
format: "esm",
223-
outDir: "lib",
224-
});
210+
export default defineConfig({"bundle":false,"clean":true,"dts":true,"entry":["src/**/*.ts"],"format":"esm","outDir":"lib"});
225211
",
226212
},
227213
}
@@ -310,14 +296,7 @@ describe("blockTSup", () => {
310296
"files": {
311297
"tsup.config.ts": "import { defineConfig } from "tsup";
312298
313-
export default defineConfig({
314-
bundle: false,
315-
clean: true,
316-
dts: true,
317-
entry: ["src/**/*.ts","!src/**/*.test.ts"],
318-
format: "esm",
319-
outDir: "lib",
320-
});
299+
export default defineConfig({"bundle":false,"clean":true,"dts":true,"entry":["src/**/*.ts","!src/**/*.test.ts"],"format":"esm","outDir":"lib"});
321300
",
322301
},
323302
"scripts": undefined,

‎src/blocks/blockTSup.ts

+12-10
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ export const blockTSup = base.createBlock({
1818
},
1919
addons: {
2020
entry: z.array(z.string()).default([]),
21+
properties: z.record(z.unknown()).default({}),
2122
runInCI: z.array(z.string()).default([]),
2223
},
2324
produce({ addons, options }) {
24-
const { entry } = addons;
25+
const { entry, properties, runInCI } = addons;
2526

2627
return {
2728
addons: [
@@ -53,7 +54,7 @@ pnpm build --watch
5354
name: "Build",
5455
steps: [
5556
{ run: "pnpm build" },
56-
...addons.runInCI.map((run) => ({ run })),
57+
...runInCI.map((run) => ({ run })),
5758
],
5859
},
5960
],
@@ -78,14 +79,15 @@ pnpm build --watch
7879
files: {
7980
"tsup.config.ts": `import { defineConfig } from "tsup";
8081
81-
export default defineConfig({
82-
bundle: false,
83-
clean: true,
84-
dts: true,
85-
entry: ${JSON.stringify(["src/**/*.ts", ...entry])},
86-
format: "esm",
87-
outDir: "lib",
88-
});
82+
export default defineConfig(${JSON.stringify({
83+
bundle: false,
84+
clean: true,
85+
dts: true,
86+
entry: ["src/**/*.ts", ...entry],
87+
format: "esm",
88+
outDir: "lib",
89+
...properties,
90+
})});
8991
`,
9092
},
9193
scripts: options.bin

‎src/blocks/blockTypeScript.test.ts

+153-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { blockTypeScript } from "./blockTypeScript.js";
55
import { optionsBase } from "./options.fakes.js";
66

77
describe("blockTypeScript", () => {
8-
test("without options.bin", () => {
8+
test("without addons or options", () => {
99
const creation = testBlock(blockTypeScript, {
1010
options: optionsBase,
1111
});
@@ -152,6 +152,158 @@ describe("blockTypeScript", () => {
152152
`);
153153
});
154154

155+
test("with addons", () => {
156+
const creation = testBlock(blockTypeScript, {
157+
addons: {
158+
compilerOptions: {
159+
strictBindCallApply: false,
160+
},
161+
},
162+
options: optionsBase,
163+
});
164+
165+
expect(creation).toMatchInlineSnapshot(`
166+
{
167+
"addons": [
168+
{
169+
"addons": {
170+
"sections": {
171+
"Type Checking": {
172+
"contents": "
173+
You should be able to see suggestions from [TypeScript](https://typescriptlang.org) in your editor for all open files.
174+
175+
However, it can be useful to run the TypeScript command-line (\`tsc\`) to type check all files in \`src/\`:
176+
177+
\`\`\`shell
178+
pnpm tsc
179+
\`\`\`
180+
181+
Add \`--watch\` to keep the type checker running in a watch mode that updates the display as you save files:
182+
183+
\`\`\`shell
184+
pnpm tsc --watch
185+
\`\`\`
186+
",
187+
},
188+
},
189+
},
190+
"block": [Function],
191+
},
192+
{
193+
"addons": {
194+
"files": {
195+
"greet.ts": "import { GreetOptions } from "./types.js";
196+
197+
export function greet(options: GreetOptions | string) {
198+
const {
199+
logger = console.log.bind(console),
200+
message,
201+
times = 1,
202+
} = typeof options === "string" ? { message: options } : options;
203+
204+
for (let i = 0; i < times; i += 1) {
205+
logger(message);
206+
}
207+
}
208+
",
209+
"index.ts": "export * from "./greet.js";
210+
export * from "./types.js";
211+
",
212+
"types.ts": "export interface GreetOptions {
213+
logger?: (message: string) => void;
214+
message: string;
215+
times?: number;
216+
}
217+
",
218+
},
219+
},
220+
"block": [Function],
221+
},
222+
{
223+
"addons": {
224+
"ignores": [
225+
"/lib",
226+
],
227+
},
228+
"block": [Function],
229+
},
230+
{
231+
"addons": {
232+
"jobs": [
233+
{
234+
"name": "Type Check",
235+
"steps": [
236+
{
237+
"run": "pnpm tsc",
238+
},
239+
],
240+
},
241+
],
242+
},
243+
"block": [Function],
244+
},
245+
{
246+
"addons": {
247+
"ignores": [
248+
"lib/",
249+
],
250+
},
251+
"block": [Function],
252+
},
253+
{
254+
"addons": {
255+
"properties": {
256+
"devDependencies": {
257+
"typescript": "5.8.2",
258+
},
259+
"files": [
260+
"lib/",
261+
],
262+
"scripts": {
263+
"tsc": "tsc",
264+
},
265+
},
266+
},
267+
"block": [Function],
268+
},
269+
{
270+
"addons": {
271+
"coverage": {
272+
"include": [
273+
"src",
274+
],
275+
},
276+
"exclude": [
277+
"lib",
278+
],
279+
},
280+
"block": [Function],
281+
},
282+
{
283+
"addons": {
284+
"debuggers": [],
285+
"settings": {
286+
"typescript.tsdk": "node_modules/typescript/lib",
287+
},
288+
"tasks": [
289+
{
290+
"detail": "Build the project",
291+
"label": "build",
292+
"script": "build",
293+
"type": "npm",
294+
},
295+
],
296+
},
297+
"block": [Function],
298+
},
299+
],
300+
"files": {
301+
"tsconfig.json": "{"compilerOptions":{"declaration":true,"declarationMap":true,"esModuleInterop":true,"module":"NodeNext","moduleResolution":"NodeNext","noEmit":true,"resolveJsonModule":true,"skipLibCheck":true,"strict":true,"target":"ES2022","strictBindCallApply":false},"include":["src"]}",
302+
},
303+
}
304+
`);
305+
});
306+
155307
test("with options.bin", () => {
156308
const creation = testBlock(blockTypeScript, {
157309
options: {

‎src/blocks/blockTypeScript.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { CompilerOptionsSchema } from "zod-tsconfig";
2+
13
import { base } from "../base.js";
24
import { getPackageDependencies } from "../data/packageData.js";
35
import { getPrimaryBin } from "./bin/getPrimaryBin.js";
@@ -15,7 +17,11 @@ export const blockTypeScript = base.createBlock({
1517
about: {
1618
name: "TypeScript",
1719
},
18-
produce({ options }) {
20+
addons: {
21+
compilerOptions: CompilerOptionsSchema.optional(),
22+
},
23+
produce({ addons, options }) {
24+
const { compilerOptions } = addons;
1925
const primaryBin = getPrimaryBin(options.bin, options.repository);
2026

2127
return {
@@ -126,6 +132,7 @@ export * from "./types.js";
126132
skipLibCheck: true,
127133
strict: true,
128134
target: "ES2022",
135+
...compilerOptions,
129136
},
130137
include: ["src"],
131138
}),

0 commit comments

Comments
 (0)
Please sign in to comment.