Fix update-node-version script for non-existent @types/node version

This commit is contained in:
Koen Vlaswinkel
2024-11-04 15:35:18 +01:00
parent d6cef2474c
commit 80a6116bef

View File

@@ -3,6 +3,7 @@ import { execSync } from "child_process";
import { outputFile, readFile, readJSON } from "fs-extra"; import { outputFile, readFile, readJSON } from "fs-extra";
import { getVersionInformation } from "./util/vscode-versions"; import { getVersionInformation } from "./util/vscode-versions";
import { fetchJson } from "./util/fetch"; import { fetchJson } from "./util/fetch";
import { SemVer } from "semver";
const extensionDirectory = resolve(__dirname, ".."); const extensionDirectory = resolve(__dirname, "..");
@@ -10,6 +11,29 @@ interface Release {
tag_name: string; tag_name: string;
} }
interface NpmViewError {
error: {
code: string;
summary: string;
detail: string;
};
}
interface ExecError extends Error {
status: number;
stdout: string;
}
function isExecError(e: unknown): e is ExecError {
return (
e instanceof Error &&
"status" in e &&
typeof e.status === "number" &&
"stdout" in e &&
typeof e.stdout === "string"
);
}
async function updateNodeVersion() { async function updateNodeVersion() {
const latestVsCodeRelease = await fetchJson<Release>( const latestVsCodeRelease = await fetchJson<Release>(
"https://api.github.com/repos/microsoft/vscode/releases/latest", "https://api.github.com/repos/microsoft/vscode/releases/latest",
@@ -49,6 +73,8 @@ async function updateNodeVersion() {
"utf8", "utf8",
); );
const nodeVersion = new SemVer(versionInformation.nodeVersion);
// The @types/node version needs to match the first two parts of the Node // The @types/node version needs to match the first two parts of the Node
// version, e.g. if the Node version is 18.17.3, the @types/node version // version, e.g. if the Node version is 18.17.3, the @types/node version
// should be 18.17.*. This corresponds with the documentation at // should be 18.17.*. This corresponds with the documentation at
@@ -56,13 +82,55 @@ async function updateNodeVersion() {
// "The patch version of the type declaration package is unrelated to the library patch version. This allows // "The patch version of the type declaration package is unrelated to the library patch version. This allows
// Definitely Typed to safely update type declarations for the same major/minor version of a library." // Definitely Typed to safely update type declarations for the same major/minor version of a library."
// 18.17.* is equivalent to >=18.17.0 <18.18.0 // 18.17.* is equivalent to >=18.17.0 <18.18.0
const typesNodeVersion = versionInformation.nodeVersion // In some cases, the @types/node version matching the exact Node version may not exist, in which case we'll try
.split(".") // the next lower minor version, and so on, until we find a version that exists.
.slice(0, 2) const typesNodeSemver = new SemVer(nodeVersion);
.join("."); typesNodeSemver.patch = 0;
// eslint-disable-next-line no-constant-condition
while (true) {
const typesNodeVersion = `${typesNodeSemver.major}.${typesNodeSemver.minor}.*`;
try {
// Check that this version actually exists
console.log(`Checking if @types/node@${typesNodeVersion} exists`);
execSync(`npm view --json "@types/node@${typesNodeVersion}"`, {
encoding: "utf-8",
stdio: "pipe",
});
console.log(`@types/node@${typesNodeVersion} exists`);
// If it exists, we can break out of this loop
break;
} catch (e: unknown) {
if (!isExecError(e)) {
throw e;
}
const error = JSON.parse(e.stdout) as NpmViewError;
if (error.error.code !== "E404") {
throw new Error(error.error.detail);
}
console.log(
`@types/node package doesn't exist for ${typesNodeVersion}, trying a lower version (${error.error.summary})`,
);
// This means the version doesn't exist, so we'll try decrementing the minor version
typesNodeSemver.minor -= 1;
if (typesNodeSemver.minor < 0) {
throw new Error(
`Could not find a suitable @types/node version for Node ${nodeVersion.format()}`,
);
}
}
}
packageJson.engines.node = `^${versionInformation.nodeVersion}`; packageJson.engines.node = `^${versionInformation.nodeVersion}`;
packageJson.devDependencies["@types/node"] = `${typesNodeVersion}.*`; packageJson.devDependencies["@types/node"] =
`${typesNodeSemver.major}.${typesNodeSemver.minor}.*`;
await outputFile( await outputFile(
join(extensionDirectory, "package.json"), join(extensionDirectory, "package.json"),