UNPKG

node-libcurl

Version:

The fastest http(s) client (and much more) for Node.js - Node.js bindings for libcurl

205 lines (182 loc) 5.96 kB
// this should not use any third party dependencies! Only native Node.js modules! const fs = require('fs') const path = require('path') /** * Parse a version string into components. * Handles both modern (3.0.16) and legacy (1.1.1n) OpenSSL version formats. * @param {string} versionString * @returns {{ major: number, minor: number, patch: number, letter: string, raw: string } | null} */ function parseVersion(versionString) { if (!versionString || typeof versionString !== 'string') { return null } // Handle versions like "3.4.1", "1.1.1n", "3.0.8" const match = versionString.match(/^(\d+)\.(\d+)\.(\d+)([a-z])?$/) if (!match) { return null } return { major: parseInt(match[1], 10), minor: parseInt(match[2], 10), patch: parseInt(match[3], 10), letter: match[4] || '', raw: versionString, } } /** * Compare two parsed versions. * @param {{ major: number, minor: number, patch: number, letter: string }} a * @param {{ major: number, minor: number, patch: number, letter: string }} b * @returns {number} -1 if a < b, 0 if a === b, 1 if a > b */ function compareVersions(a, b) { if (a.major !== b.major) return a.major - b.major if (a.minor !== b.minor) return a.minor - b.minor if (a.patch !== b.patch) return a.patch - b.patch // Handle letter suffix (for 1.1.1a < 1.1.1b < 1.1.1n) if (a.letter && b.letter) { return a.letter.localeCompare(b.letter) } // Version without letter comes before version with letter if (a.letter && !b.letter) return 1 if (!a.letter && b.letter) return -1 return 0 } /** * Get available OpenSSL versions from vcpkg registry. * @param {string} vcpkgRoot - Path to vcpkg installation * @returns {string[] | null} Array of version strings, or null if not found */ function getAvailableVersions(vcpkgRoot) { const versionsFile = path.join(vcpkgRoot, 'versions', 'o-', 'openssl.json') if (!fs.existsSync(versionsFile)) { return null } try { const data = JSON.parse(fs.readFileSync(versionsFile, 'utf8')) if (!data.versions || !Array.isArray(data.versions)) { return null } return data.versions.map((v) => v.version).filter(Boolean) } catch { return null } } /** * Find the best matching OpenSSL version from available versions. * * Priority: * 1. Exact match * 2. Higher patch on same minor line (3.0.17, 3.0.18, ...) * 3. Lower patch on same minor line (3.0.15, 3.0.14, ... - pick highest) * 4. Lowest version on next minor line (3.1.0) * 5. Continue to higher minors if needed * 6. Fall back to original version * * @param {string} targetVersion - The desired OpenSSL version * @param {string[]} availableVersions - List of available versions in vcpkg * @returns {{ version: string, isExact: boolean, message: string | null }} */ function findBestVersion(targetVersion, availableVersions) { const target = parseVersion(targetVersion) if (!target) { return { version: targetVersion, isExact: false, message: `Could not parse version "${targetVersion}", using as-is`, } } // Parse all available versions const parsed = availableVersions .map((v) => parseVersion(v)) .filter((v) => v !== null) if (parsed.length === 0) { return { version: targetVersion, isExact: false, message: 'No versions found in vcpkg registry', } } // Check for exact match const exactMatch = parsed.find( (v) => v.major === target.major && v.minor === target.minor && v.patch === target.patch && v.letter === target.letter, ) if (exactMatch) { return { version: exactMatch.raw, isExact: true, message: null } } // Strategy 1: Find higher patch on same minor line const sameMinorHigher = parsed .filter( (v) => v.major === target.major && v.minor === target.minor && compareVersions(v, target) > 0, ) .sort((a, b) => compareVersions(a, b)) // Ascending to get closest higher if (sameMinorHigher.length > 0) { const best = sameMinorHigher[0] return { version: best.raw, isExact: false, message: `Newer patch on same ${target.major}.${target.minor}.x line`, } } // Strategy 2: Find lower patch on same minor line (pick highest available) const sameMinorLower = parsed .filter( (v) => v.major === target.major && v.minor === target.minor && compareVersions(v, target) < 0, ) .sort((a, b) => -compareVersions(a, b)) // Descending to get highest lower if (sameMinorLower.length > 0) { const best = sameMinorLower[0] return { version: best.raw, isExact: false, message: `Closest available on ${target.major}.${target.minor}.x line`, } } // Strategy 3: Find lowest version on next minor line(s) with same major const higherMinors = parsed .filter((v) => v.major === target.major && v.minor > target.minor) .sort((a, b) => compareVersions(a, b)) // Ascending if (higherMinors.length > 0) { const best = higherMinors[0] return { version: best.raw, isExact: false, message: `No ${target.major}.${target.minor}.x versions available, using ${best.major}.${best.minor}.x`, } } // Strategy 4: Look at next major version (rare case) const higherMajors = parsed .filter((v) => v.major > target.major) .sort((a, b) => compareVersions(a, b)) if (higherMajors.length > 0) { const best = higherMajors[0] return { version: best.raw, isExact: false, message: `WARNING: No OpenSSL ${target.major}.x available, using ${best.major}.x (major version change)`, } } // No suitable version found - return target and let vcpkg fail return { version: targetVersion, isExact: false, message: 'No compatible OpenSSL version found in vcpkg registry', } } module.exports = { parseVersion, compareVersions, getAvailableVersions, findBestVersion, }