import { execFileSync } from 'node:child_process'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const VERSION_PATTERN = /^(?:v)?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/; function parseVersion(value, label) { const normalized = String(value ?? '').trim(); const match = normalized.match(VERSION_PATTERN); if (!match) { throw new Error(`${label} 版本格式无效:${normalized || '(空)'}`); } return Object.freeze({ raw: normalized.replace(/^v/, ''), major: Number(match[1]) }); } /** * 项目只验证开发机已经提供的运行时,不安装或切换 Node。严格固定主版本可以让 * 本地源码运行、CI 和生产镜像使用同一语义,避免跨主版本的 ESM 与工具链差异。 */ export function assertSupportedRuntime({ nodeVersion, pnpmVersion }) { const node = parseVersion(nodeVersion, 'Node.js'); const pnpm = parseVersion(pnpmVersion, 'pnpm'); if (node.major !== 22) { throw new Error(`Node.js 必须为 22.x,实际 ${node.raw}`); } if (pnpm.major !== 10) { throw new Error(`pnpm 必须为 10.x,实际 ${pnpm.raw}`); } return Object.freeze({ nodeVersion: node.raw, pnpmVersion: pnpm.raw }); } function runCommandLine() { const pnpmVersion = execFileSync('pnpm', ['--version'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], }).trim(); const result = assertSupportedRuntime({ nodeVersion: process.version, pnpmVersion }); process.stdout.write( `运行时验证通过:Node.js ${result.nodeVersion},pnpm ${result.pnpmVersion}\n`, ); } if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { runCommandLine(); }