1import { readFileSync, writeFileSync } from 'fs'; 2import https from 'https'; 3 4const srcRoot = new URL('../../', import.meta.url); 5 6const isRelease = () => { 7 const re = /#define NODE_VERSION_IS_RELEASE 0/; 8 const file = new URL('./src/node_version.h', srcRoot); 9 return !re.test(readFileSync(file, { encoding: 'utf8' })); 10}; 11 12const getUrl = (url) => { 13 return new Promise((resolve, reject) => { 14 const request = https.get(url, { timeout: 30000 }, (response) => { 15 if (response.statusCode !== 200) { 16 reject(new Error( 17 `Failed to get ${url}, status code ${response.statusCode}`)); 18 } 19 response.setEncoding('utf8'); 20 let body = ''; 21 response.on('aborted', () => reject()); 22 response.on('data', (data) => body += data); 23 response.on('end', () => resolve(body)); 24 }); 25 request.on('error', (err) => reject(err)); 26 request.on('timeout', () => request.abort()); 27 }); 28}; 29 30const kNoInternet = !!process.env.NODE_TEST_NO_INTERNET; 31const outFile = (process.argv.length > 2 ? process.argv[2] : undefined); 32 33async function versions() { 34 // The CHANGELOG.md on release branches may not reference newer semver 35 // majors of Node.js so fetch and parse the version from the master branch. 36 const url = 37 'https://raw.githubusercontent.com/nodejs/node/HEAD/CHANGELOG.md'; 38 let changelog; 39 const file = new URL('./CHANGELOG.md', srcRoot); 40 if (kNoInternet) { 41 changelog = readFileSync(file, { encoding: 'utf8' }); 42 } else { 43 try { 44 changelog = await getUrl(url); 45 } catch (e) { 46 // Fail if this is a release build, otherwise fallback to local files. 47 if (isRelease()) { 48 throw e; 49 } else { 50 console.warn(`Unable to retrieve ${url}. Falling back to ${file}.`); 51 changelog = readFileSync(file, { encoding: 'utf8' }); 52 } 53 } 54 } 55 const ltsRE = /Long Term Support/i; 56 const versionRE = /\* \[Node\.js ([0-9.]+)\]\S+ (.*)\r?\n/g; 57 const _versions = []; 58 let match; 59 while ((match = versionRE.exec(changelog)) != null) { 60 const entry = { num: `${match[1]}.x` }; 61 if (ltsRE.test(match[2])) { 62 entry.lts = true; 63 } 64 _versions.push(entry); 65 } 66 return _versions; 67} 68 69versions().then((v) => { 70 if (outFile) { 71 writeFileSync(outFile, JSON.stringify(v)); 72 } else { 73 console.log(JSON.stringify(v)); 74 } 75}).catch((err) => { 76 console.error(err); 77 process.exit(1); 78}); 79