Something went wrong. Try again.
Monorepo for the nibling.run platform
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465// Checks nodejs.org's release index for LTS releases newer than the pin, on the pin's// major and any extra majors given on the command line. Detection only: this never// downloads a tarball or runs a check, see node-release-check.mjs for that.//// node scripts/node-releases.mjs [--index=<file>] [--json] [extraMajor…]// Reads https://nodejs.org/dist/index.json (or --index for an offline/deterministic// run) and, for each tracked major, reports the newest release with `lts !== false`// and whether it is newer than the pin. --json prints the raw report instead of// lines of text. Exits 0 either way; callers decide what "newer" means for them.import { readFileSync } from "node:fs";import semver from "semver";import { PINNED } from "./pinned-node.mjs";
const INDEX_URL = "https://nodejs.org/dist/index.json";
/** The majors to check: the pin's major plus any extras, deduped and sorted. */export function trackedMajors(pinned, extra = []) { return [...new Set([semver.major(pinned), ...extra.map(Number)])].sort((a, b) => a - b);}
/** Pure: pick the newest LTS release per tracked major from a raw index.json array, and * say whether it is newer than the pin. `newer` on the pin's own major is a real * semver comparison; on an extra major (which the pin can't be compared to) it is true * whenever an LTS release exists, since any such line is one we don't have at all. */export function selectReleases(index, pinned, majors) { const pinnedMajor = semver.major(pinned); return majors.map((major) => { const latest = index .filter((r) => r.lts !== false) .map((r) => ({ ...r, version: r.version.replace(/^v/, "") })) .filter((r) => semver.major(r.version) === major) .reduce((best, r) => (!best || semver.gt(r.version, best.version) ? r : best), null); const newer = latest ? (major === pinnedMajor ? semver.gt(latest.version, pinned) : true) : false; return { major, latest: latest ? { version: latest.version, date: latest.date, lts: latest.lts } : null, newer }; });}
async function fetchIndex(url) { const res = await fetch(url); if (!res.ok) throw new Error(`GET ${url}: ${res.status}`); return res.json();}
async function main() { const args = process.argv.slice(2); const indexFlag = args.find((a) => a.startsWith("--index="))?.slice("--index=".length); const json = args.includes("--json"); const extra = args.filter((a) => !a.startsWith("--"));
const index = indexFlag ? JSON.parse(readFileSync(indexFlag, "utf8")) : await fetchIndex(INDEX_URL); const report = selectReleases(index, PINNED, trackedMajors(PINNED, extra));
if (json) { console.log(JSON.stringify({ pinned: PINNED, releases: report }, null, 2)); } else { console.log(`pin: ${PINNED}`); for (const r of report) { if (!r.latest) console.log(`${r.major}: no LTS release`); else console.log(`${r.major}: latest LTS ${r.latest.version} (${r.latest.date})${r.newer ? " — newer than pin" : " — up to date"}`); } }}
if (import.meta.url === `file://${process.argv[1]}`) main();