Skip to content

Commit 80a6116

Browse files
committed
Fix update-node-version script for non-existent @types/node version
1 parent d6cef24 commit 80a6116

File tree

1 file changed

+73
-5
lines changed

1 file changed

+73
-5
lines changed

extensions/ql-vscode/scripts/update-node-version.ts

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,37 @@ import { execSync } from "child_process";
33
import { outputFile, readFile, readJSON } from "fs-extra";
44
import { getVersionInformation } from "./util/vscode-versions";
55
import { fetchJson } from "./util/fetch";
6+
import { SemVer } from "semver";
67

78
const extensionDirectory = resolve(__dirname, "..");
89

910
interface Release {
1011
tag_name: string;
1112
}
1213

14+
interface NpmViewError {
15+
error: {
16+
code: string;
17+
summary: string;
18+
detail: string;
19+
};
20+
}
21+
22+
interface ExecError extends Error {
23+
status: number;
24+
stdout: string;
25+
}
26+
27+
function isExecError(e: unknown): e is ExecError {
28+
return (
29+
e instanceof Error &&
30+
"status" in e &&
31+
typeof e.status === "number" &&
32+
"stdout" in e &&
33+
typeof e.stdout === "string"
34+
);
35+
}
36+
1337
async function updateNodeVersion() {
1438
const latestVsCodeRelease = await fetchJson<Release>(
1539
"https://api.github.com/repos/microsoft/vscode/releases/latest",
@@ -49,20 +73,64 @@ async function updateNodeVersion() {
4973
"utf8",
5074
);
5175

76+
const nodeVersion = new SemVer(versionInformation.nodeVersion);
77+
5278
// The @types/node version needs to match the first two parts of the Node
5379
// version, e.g. if the Node version is 18.17.3, the @types/node version
5480
// should be 18.17.*. This corresponds with the documentation at
5581
// https://github.com/definitelytyped/definitelytyped#how-do-definitely-typed-package-versions-relate-to-versions-of-the-corresponding-library
5682
// "The patch version of the type declaration package is unrelated to the library patch version. This allows
5783
// Definitely Typed to safely update type declarations for the same major/minor version of a library."
5884
// 18.17.* is equivalent to >=18.17.0 <18.18.0
59-
const typesNodeVersion = versionInformation.nodeVersion
60-
.split(".")
61-
.slice(0, 2)
62-
.join(".");
85+
// In some cases, the @types/node version matching the exact Node version may not exist, in which case we'll try
86+
// the next lower minor version, and so on, until we find a version that exists.
87+
const typesNodeSemver = new SemVer(nodeVersion);
88+
typesNodeSemver.patch = 0;
89+
90+
// eslint-disable-next-line no-constant-condition
91+
while (true) {
92+
const typesNodeVersion = `${typesNodeSemver.major}.${typesNodeSemver.minor}.*`;
93+
94+
try {
95+
// Check that this version actually exists
96+
console.log(`Checking if @types/node@${typesNodeVersion} exists`);
97+
98+
execSync(`npm view --json "@types/node@${typesNodeVersion}"`, {
99+
encoding: "utf-8",
100+
stdio: "pipe",
101+
});
102+
103+
console.log(`@types/node@${typesNodeVersion} exists`);
104+
105+
// If it exists, we can break out of this loop
106+
break;
107+
} catch (e: unknown) {
108+
if (!isExecError(e)) {
109+
throw e;
110+
}
111+
112+
const error = JSON.parse(e.stdout) as NpmViewError;
113+
if (error.error.code !== "E404") {
114+
throw new Error(error.error.detail);
115+
}
116+
117+
console.log(
118+
`@types/node package doesn't exist for ${typesNodeVersion}, trying a lower version (${error.error.summary})`,
119+
);
120+
121+
// This means the version doesn't exist, so we'll try decrementing the minor version
122+
typesNodeSemver.minor -= 1;
123+
if (typesNodeSemver.minor < 0) {
124+
throw new Error(
125+
`Could not find a suitable @types/node version for Node ${nodeVersion.format()}`,
126+
);
127+
}
128+
}
129+
}
63130

64131
packageJson.engines.node = `^${versionInformation.nodeVersion}`;
65-
packageJson.devDependencies["@types/node"] = `${typesNodeVersion}.*`;
132+
packageJson.devDependencies["@types/node"] =
133+
`${typesNodeSemver.major}.${typesNodeSemver.minor}.*`;
66134

67135
await outputFile(
68136
join(extensionDirectory, "package.json"),

0 commit comments

Comments
 (0)