Skip to content

Commit 4ef6223

Browse files
authoredMar 27, 2025··
fix: coerce dependency versions in semver parsing (#2045)
## PR Checklist - [x] Addresses an existing open issue: fixes #2043 - [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 I couldn't figure out how to get the exact failure case from #2043, weirdly enough. But this PR's invalid semver handling happens to fix that failure in `debug-for-file` locally for me. 🎁
1 parent d2103ce commit 4ef6223

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed
 

‎src/blocks/blockPackageJson.test.ts

+31-1
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ describe("blockPackageJson", () => {
260260
`);
261261
});
262262

263-
it("preserves an existing dependency when the addon has an older pinned version", () => {
263+
it("preserves an existing dependency when the addon has an invalid version", () => {
264264
const dependency = "test-dependency";
265265
const creation = testBlock(blockPackageJson, {
266266
addons: {
@@ -318,6 +318,36 @@ describe("blockPackageJson", () => {
318318
`);
319319
});
320320

321+
it("uses the addon's version when the existing equivalent is invalid semver", () => {
322+
const dependency = "test-dependency";
323+
const creation = testBlock(blockPackageJson, {
324+
addons: {
325+
properties: {
326+
dependencies: {
327+
[dependency]: "1.0.0",
328+
},
329+
},
330+
},
331+
options: {
332+
...optionsBase,
333+
packageData: {
334+
dependencies: {
335+
[dependency]: "next",
336+
},
337+
},
338+
},
339+
});
340+
341+
expect(
342+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-member-access
343+
JSON.parse(creation.files!["package.json"] as string).dependencies,
344+
).toMatchInlineSnapshot(`
345+
{
346+
"test-dependency": "1.0.0",
347+
}
348+
`);
349+
});
350+
321351
it("preserves an existing dependency when the addon has an older version minimum", () => {
322352
const dependency = "test-dependency";
323353
const creation = testBlock(blockPackageJson, {

‎src/blocks/blockPackageJson.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,20 @@ function collectBinFiles(bin: Record<string, string> | string | undefined) {
119119
}
120120

121121
function removeRangePrefix(version: string) {
122-
return version.replaceAll(/[\^~><=]/gu, "").split(" ")[0];
122+
const raw = version.replaceAll(/[\^~><=]/gu, "").split(" ")[0];
123+
124+
return semver.coerce(raw) ?? raw;
123125
}
124126

125127
function useLargerVersion(existing: string | undefined, replacement: string) {
126-
if (!existing) {
128+
if (!existing || existing === replacement) {
127129
return replacement;
128130
}
129131

130-
return semver.gt(removeRangePrefix(existing), removeRangePrefix(replacement))
132+
const existingCoerced = semver.coerce(removeRangePrefix(existing));
133+
134+
return existingCoerced &&
135+
semver.gt(existingCoerced, removeRangePrefix(replacement))
131136
? existing
132137
: replacement;
133138
}

0 commit comments

Comments
 (0)
Please sign in to comment.