diff --git a/package-lock.json b/package-lock.json index c1bb3ad8..3e875f60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "@types/chrome": "^0.0.310", "@types/mocha": "^10.0.10", "@types/mri": "^1.1.1", - "@types/node": "^20.12.7", + "@types/node": "^25.6.0", "@types/node-fetch": "^2.6.2", "@types/sinon": "^17.0.4", "@types/tar": "^6.1.2", @@ -2147,13 +2147,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.17.26", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.26.tgz", - "integrity": "sha512-x9T6TLS76RIBGB0X81k+9697cNZel+f/v+BR8gzKNqISC3MhHHWoHY6XIEDY0E8psIJmCEMXqxjw7Np1u/mysA==", + "version": "25.6.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", + "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~7.19.0" } }, "node_modules/@types/node-fetch": { @@ -11584,9 +11584,9 @@ } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "version": "7.19.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", + "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", "dev": true, "license": "MIT" }, diff --git a/package.json b/package.json index 8056ba33..29b0f7e2 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "@types/chrome": "^0.0.310", "@types/mocha": "^10.0.10", "@types/mri": "^1.1.1", - "@types/node": "^20.12.7", + "@types/node": "^25.6.0", "@types/node-fetch": "^2.6.2", "@types/sinon": "^17.0.4", "@types/tar": "^6.1.2", diff --git a/tools/fetch-preact-versions.mjs b/tools/fetch-preact-versions.mjs index adb43dba..566f2583 100644 --- a/tools/fetch-preact-versions.mjs +++ b/tools/fetch-preact-versions.mjs @@ -1,5 +1,6 @@ import * as util from "util"; import fs from "fs"; +import { glob } from "fs/promises"; import path from "path"; import * as kl from "kolorist"; import { pipeline } from "stream"; @@ -11,30 +12,85 @@ const streamPipeline = util.promisify(pipeline); /* eslint-disable no-console */ /** - * @typedef {{time: Record, versions: Record}} NPMResponse + * @typedef {{versions: Record, "dist-tags": Record}} NPMResponse */ +const root = path.join(__dirname, ".."); +const versionReg = /\b(?:10|11)\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?\b/g; + +function sortVersions(a, b) { + const [releaseA, prereleaseA] = a.split("-"); + const [releaseB, prereleaseB] = b.split("-"); + const semverA = releaseA.split(".").map(Number); + const semverB = releaseB.split(".").map(Number); + + for (const i of [0, 1, 2]) { + const diff = semverA[i] - semverB[i]; + if (diff !== 0) return diff; + } + + if (!prereleaseA && prereleaseB) return 1; + if (prereleaseA && !prereleaseB) return -1; + if (!prereleaseA && !prereleaseB) return 0; + + const partsA = prereleaseA.split("."); + const partsB = prereleaseB.split("."); + for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) { + if (partsA[i] === undefined) return -1; + if (partsB[i] === undefined) return 1; + + const numA = /^\d+$/.test(partsA[i]); + const numB = /^\d+$/.test(partsB[i]); + if (numA && numB && +partsA[i] !== +partsB[i]) { + return +partsA[i] - +partsB[i]; + } + if (numA !== numB) return numA ? -1 : 1; + if (partsA[i] !== partsB[i]) return partsA[i] < partsB[i] ? -1 : 1; + } + + return 0; +} + (async () => { const res = await fetch("https://registry.npmjs.org/preact"); /** @type {NPMResponse} */ const json = await res.json(); - const versions = Object.keys(json.time).reduce((acc, version) => { - if (/modified|created/.test(version)) { - return acc; - } + const publishedVersions = Object.keys(json.versions); + const versionsToFetch = new Set([json["dist-tags"].latest]); - const semver = version.split("."); - if (+semver[0] < 10 || (+semver[0] === 10 && +semver[1] < 1)) { - return acc; - } + for await (const file of glob("test-e2e/tests/**/*.test.ts", { cwd: root })) { + const text = fs + .readFileSync(path.join(root, file), "utf8") + .replace(/\/\*[\s\S]*?\*\//g, "") + .replace(/\/\/.*/g, ""); + text.match(versionReg)?.forEach(version => versionsToFetch.add(version)); + } - acc.push(version); - return acc; - }, []); + const pkg = fs.readFileSync(path.join(root, "package.json"), "utf8"); + pkg.replace(/PREACT_VERSION=(\d+)/g, (_, major) => { + const matching = publishedVersions.filter(v => v.startsWith(`${major}.`)); + const stable = matching.filter(v => !v.includes("-")); + versionsToFetch.add( + (stable.length ? stable : matching).sort(sortVersions).at(-1), + ); + return ""; + }); + + const extras = process.argv.slice(2); + if (process.env.PREACT_VERSION?.match(versionReg)) { + extras.push(process.env.PREACT_VERSION); + } + + for (const arg of extras) { + const version = arg.replace(/^preact@/, "").replace(/^v/, ""); + if (!json.versions[version]) + throw new Error(`Unknown preact version "${arg}"`); + versionsToFetch.add(version); + } - for (const version of versions) { + for (const version of [...versionsToFetch].sort(sortVersions)) { const tarball = json.versions[version].dist.tarball; const tgz = path.basename(tarball); const dest = path.join(