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