build(GOV-009): 建立 Node 与工作区基线

This commit is contained in:
2026-08-13 15:54:07 +08:00
parent b3d8e29f52
commit 258a2d21f6
8 changed files with 138 additions and 1 deletions
+45
View File
@@ -0,0 +1,45 @@
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();
}
+35
View File
@@ -0,0 +1,35 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { assertSupportedRuntime } from './verify-runtime.mjs';
test('只接受 Node 22 与 pnpm 10', () => {
assert.doesNotThrow(() =>
assertSupportedRuntime({ nodeVersion: '22.11.0', pnpmVersion: '10.25.0' }),
);
for (const nodeVersion of ['20.20.2', '24.0.0']) {
assert.throws(
() => assertSupportedRuntime({ nodeVersion, pnpmVersion: '10.25.0' }),
new RegExp(`Node\\.js 必须为 22\\.x,实际 ${nodeVersion.replaceAll('.', '\\.')}`),
);
}
for (const pnpmVersion of ['9.15.0', '11.0.0']) {
assert.throws(
() => assertSupportedRuntime({ nodeVersion: '22.11.0', pnpmVersion }),
new RegExp(`pnpm 必须为 10\\.x,实际 ${pnpmVersion.replaceAll('.', '\\.')}`),
);
}
});
test('拒绝无法解析的运行时版本', () => {
for (const runtime of [
{ nodeVersion: '', pnpmVersion: '10.25.0' },
{ nodeVersion: 'v22', pnpmVersion: '10.25.0' },
{ nodeVersion: '22.11.0', pnpmVersion: '' },
{ nodeVersion: '22.11.0', pnpmVersion: 'ten' },
]) {
assert.throws(() => assertSupportedRuntime(runtime), /版本格式无效/);
}
});