Skip to content

Commit 8f6039d

Browse files
fix: handle subset file matches in blockPackageJson (#2107)
<!-- 👋 Hi, thanks for sending a PR to create-typescript-app! 🎁 Please fill out all fields below and make sure each item is true and [x] checked. Otherwise we may not be able to review your PR. --> ## PR Checklist - [x] Addresses an existing open issue: fixes #2106 - [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 bbb355e commit 8f6039d

File tree

2 files changed

+56
-15
lines changed

2 files changed

+56
-15
lines changed

src/blocks/blockPackageJson.test.ts

+37-10
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ describe("blockPackageJson", () => {
1717
expect(creation).toMatchInlineSnapshot(`
1818
{
1919
"files": {
20-
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"engines":{"node":">=20.12.0"}}",
20+
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"engines":{"node":">=20.12.0"}}",
2121
},
2222
"scripts": [
2323
{
@@ -50,7 +50,7 @@ describe("blockPackageJson", () => {
5050
},
5151
],
5252
"files": {
53-
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"engines":{"node":">=20.12.0"}}",
53+
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"engines":{"node":">=20.12.0"}}",
5454
},
5555
"scripts": [
5656
{
@@ -81,7 +81,7 @@ describe("blockPackageJson", () => {
8181
expect(creation).toMatchInlineSnapshot(`
8282
{
8383
"files": {
84-
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"dependencies":{"is-odd":"1.2.3"},"engines":{"node":">=20.12.0"},"other":true}",
84+
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"dependencies":{"is-odd":"1.2.3"},"engines":{"node":">=20.12.0"},"other":true}",
8585
},
8686
"scripts": [
8787
{
@@ -116,7 +116,7 @@ describe("blockPackageJson", () => {
116116
expect(creation).toMatchInlineSnapshot(`
117117
{
118118
"files": {
119-
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"dependencies":{"is-odd":"1.2.3"},"devDependencies":{"is-even":"4.5.6"},"engines":{"node":">=20.12.0"},"other":true}",
119+
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"dependencies":{"is-odd":"1.2.3"},"devDependencies":{"is-even":"4.5.6"},"engines":{"node":">=20.12.0"},"other":true}",
120120
},
121121
"scripts": [
122122
{
@@ -131,6 +131,33 @@ describe("blockPackageJson", () => {
131131
`);
132132
});
133133

134+
test("with addons adding overlapping files", () => {
135+
const creation = testBlock(blockPackageJson, {
136+
addons: {
137+
properties: {
138+
files: ["README.md", "LICENSE.md", "lib/", "lib/bin/file.js"],
139+
},
140+
},
141+
options,
142+
});
143+
144+
expect(creation).toMatchInlineSnapshot(`
145+
{
146+
"files": {
147+
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"author":{"email":"[email protected]"},"type":"module","files":["LICENSE.md","README.md","lib/","package.json"],"engines":{"node":">=20.12.0"}}",
148+
},
149+
"scripts": [
150+
{
151+
"commands": [
152+
"pnpm install --no-frozen-lockfile",
153+
],
154+
"phase": 1,
155+
},
156+
],
157+
}
158+
`);
159+
});
160+
134161
test("with keywords", () => {
135162
const creation = testBlock(blockPackageJson, {
136163
options: {
@@ -142,7 +169,7 @@ describe("blockPackageJson", () => {
142169
expect(creation).toMatchInlineSnapshot(`
143170
{
144171
"files": {
145-
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","keywords":["abc","def ghi"],"repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"engines":{"node":">=20.12.0"}}",
172+
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","keywords":["abc","def ghi"],"repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"engines":{"node":">=20.12.0"}}",
146173
},
147174
"scripts": [
148175
{
@@ -170,7 +197,7 @@ describe("blockPackageJson", () => {
170197
expect(creation).toMatchInlineSnapshot(`
171198
{
172199
"files": {
173-
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"packageManager":"[email protected]","engines":{"node":">=22.0.0"}}",
200+
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"packageManager":"[email protected]","engines":{"node":">=22.0.0"}}",
174201
},
175202
"scripts": [
176203
{
@@ -195,7 +222,7 @@ describe("blockPackageJson", () => {
195222
expect(creation).toMatchInlineSnapshot(`
196223
{
197224
"files": {
198-
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"[email protected]"},"type":"module","bin":"bin/index.js","files":["README.md","bin/index.js","package.json"],"engines":{"node":">=20.12.0"}}",
225+
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"author":{"email":"[email protected]"},"type":"module","bin":"bin/index.js","files":["README.md","bin/index.js","package.json"],"engines":{"node":">=20.12.0"}}",
199226
},
200227
"scripts": [
201228
{
@@ -223,7 +250,7 @@ describe("blockPackageJson", () => {
223250
expect(creation).toMatchInlineSnapshot(`
224251
{
225252
"files": {
226-
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"[email protected]"},"type":"module","bin":{"absolute":"bin/absolute.js","relative":"./bin/relative.js"},"files":["README.md","bin/absolute.js","bin/relative.js","package.json"],"engines":{"node":">=20.12.0"}}",
253+
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"author":{"email":"[email protected]"},"type":"module","bin":{"absolute":"bin/absolute.js","relative":"./bin/relative.js"},"files":["README.md","bin/absolute.js","bin/relative.js","package.json"],"engines":{"node":">=20.12.0"}}",
227254
},
228255
"scripts": [
229256
{
@@ -258,7 +285,7 @@ describe("blockPackageJson", () => {
258285
expect(creation).toMatchInlineSnapshot(`
259286
{
260287
"files": {
261-
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"peerDependencies":{"@types/estree":">=1","eslint":">=8"},"peerDependenciesMeta":{"@types/estree":{"optional":true}},"engines":{"node":">=20.12.0"}}",
288+
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"peerDependencies":{"@types/estree":">=1","eslint":">=8"},"peerDependenciesMeta":{"@types/estree":{"optional":true}},"engines":{"node":">=20.12.0"}}",
262289
},
263290
"scripts": [
264291
{
@@ -281,7 +308,7 @@ describe("blockPackageJson", () => {
281308
expect(creation).toMatchInlineSnapshot(`
282309
{
283310
"files": {
284-
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"license":"MIT","author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"engines":{"node":">=20.12.0"}}",
311+
"package.json": "{"name":"test-repository","version":"0.0.0","description":"A very very very very very very very very very very very very very very very very long HTML-ish description ending with an emoji. 🧵","repository":{"type":"git","url":"git+https://github.com/test-owner/test-repository.git"},"author":{"email":"[email protected]"},"type":"module","files":["README.md","package.json"],"engines":{"node":">=20.12.0"}}",
285312
},
286313
"scripts": [
287314
{

src/blocks/blockPackageJson.ts

+19-5
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,13 @@ export const blockPackageJson = base.createBlock({
5959
...(options.pnpm && {
6060
packageManager: `pnpm@${options.pnpm}`,
6161
}),
62-
files: [
62+
files: processFiles([
6363
...collectBinFiles(options.bin),
6464
...(addons.properties.files ?? []),
6565
"package.json",
6666
"README.md",
67-
]
68-
.filter(Boolean)
69-
.sort(),
67+
]),
7068
keywords: options.keywords,
71-
license: "MIT",
7269
name: options.repository,
7370
repository: {
7471
type: "git",
@@ -112,6 +109,23 @@ function collectBinFiles(bin: Record<string, string> | string | undefined) {
112109
return files.map((file) => file.replace(/^\.\//, ""));
113110
}
114111

112+
function processFiles(files: string[]) {
113+
// First sort so that shorter entries are first (e.g. "lib/")...
114+
const sortedByLength = files
115+
.filter(Boolean)
116+
.sort((a, b) => a.length - b.length);
117+
118+
// ...then remove entries captured by earlier directories (e.g. "lib/index.js")
119+
return sortedByLength
120+
.filter(
121+
(file, i) =>
122+
!sortedByLength
123+
.slice(0, i)
124+
.some((earlier) => earlier.endsWith("/") && file.startsWith(earlier)),
125+
)
126+
.sort();
127+
}
128+
115129
function removeRangePrefix(version: string) {
116130
const raw = version.replaceAll(/[\^~><=]/gu, "").split(" ")[0];
117131

0 commit comments

Comments
 (0)