import semver from 'semver'; import upath from 'upath'; import { logger } from '../../../../logger/index.ts'; import type { ToolConstraint } from '../../../../util/exec/types.ts'; import { readLocalFile } from '../../../../util/fs/index.ts'; import { newlineRegex, regEx } from '../../../../util/regex.ts'; import type { PostUpdateConfig, Upgrade } from '../../types.ts'; import type { LazyPackageJson } from './types.ts'; async function getNodeFile(filename: string): Promise { try { // TODO #22198 const constraint = (await readLocalFile(filename, 'utf8'))! .split(newlineRegex)[0] .replace(regEx(/^v/), ''); if (semver.validRange(constraint)) { logger.debug(`Using node constraint "${constraint}" from ${filename}`); return constraint; } } catch { // do nothing } return null; } async function getPackageJsonConstraint( pkg: LazyPackageJson, ): Promise { const pkgJson = await pkg.getValue(); if (pkgJson.volta?.node) { const constraint = pkgJson.volta.node; // v8 ignore else -- TODO: add test #40625 if (semver.validRange(constraint)) { logger.debug( `Using node constraint "${constraint}" from package.json volta`, ); return constraint; } } if (pkgJson.engines?.node) { const constraint = pkgJson.engines.node; // v8 ignore else -- TODO: add test #40625 if (semver.validRange(constraint)) { logger.debug( `Using node constraint "${constraint}" from package.json engines`, ); return constraint; } } return null; } // export only for testing export async function getNodeConstraint( config: Partial, upgrades: Upgrade[], lockFileDir: string, pkg: LazyPackageJson, ): Promise { const constraint = getNodeUpdate(upgrades) ?? config.constraints?.node ?? (await getNodeFile(upath.join(lockFileDir, '.nvmrc'))) ?? (await getNodeFile(upath.join(lockFileDir, '.node-version'))) ?? (await getPackageJsonConstraint(pkg)); if (!constraint) { logger.debug('No node constraint found - using latest'); } return constraint; } export function getNodeUpdate(upgrades: Upgrade[]): string | undefined { return upgrades.find((u) => u.depName === 'node')?.newValue; } export async function getNodeToolConstraint( config: Partial, upgrades: Upgrade[], lockFileDir: string, pkg: LazyPackageJson, ): Promise { const constraint = await getNodeConstraint( config, upgrades, lockFileDir, pkg, ); return { toolName: 'node', constraint, }; }