mirror of
https://github.com/THU-MAIC/OpenMAIC.git
synced 2026-10-03 17:59:34 +08:00
Why: - The root Node 20.9 contract predates direct runtime dependencies whose declared minimums now reach Node 22.19. - README, contributor, localized docs, and the OpenMAIC extension skill repeated the stale supported-version claim. What: - Raise the root Node minimum to 22.19 and align every operator, contributor, locale, and skill prerequisite. - Add a check that compares the root minimum with installed direct production dependency engine minimums. - Run the new contract check in CI after the frozen dependency install. Risk: - This changes the declared minimum only; no upper bound is added and Node 24 compatibility remains a separate concern. - The localized docs build was validated with the independent #1306 boundary fix from PR #1307, which is not included here. Tests: - RED on the base: engine check reported pi-agent-core, pi-ai, svg-pathdata, and undici floors - GREEN: root minimum 22.19 satisfies 35 engine-constrained direct dependencies - Node 20 lockfile-only install reports the root unsupported-engine warning - Node 22 frozen install and postinstall - Docs build with PR #1307 boundary: 34 pages and all locale postexport checks; docs types:check - Root Prettier, ESLint, TypeScript, i18n, package-version, and internal-dependency gates - Root pnpm test: 7137 passed, 81 skipped Live Docs: - GitHub issue #1304 tracks the Node contract; #1306 / PR #1307 tracks the separate docs-build prerequisite. Co-authored-by: wyuc <wang-yc24@mails.tsinghua.edu.cn>
74 lines
2.3 KiB
JavaScript
74 lines
2.3 KiB
JavaScript
import { readFileSync } from 'node:fs';
|
|
import { dirname, join } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import semver from 'semver';
|
|
|
|
const repositoryRoot = dirname(fileURLToPath(new URL('../package.json', import.meta.url)));
|
|
|
|
function readManifest(path) {
|
|
return JSON.parse(readFileSync(path, 'utf8'));
|
|
}
|
|
|
|
function fail(headline, problems) {
|
|
console.error([headline, ...problems.map((problem) => `- ${problem}`)].join('\n'));
|
|
process.exit(1);
|
|
}
|
|
|
|
const rootManifest = readManifest(join(repositoryRoot, 'package.json'));
|
|
const rootRange = rootManifest.engines?.node;
|
|
const rootMinimum = rootRange ? semver.minVersion(rootRange) : null;
|
|
if (!rootRange || rootMinimum === null) {
|
|
fail('The root Node engine contract is invalid:', [
|
|
`package.json engines.node must be a valid semver range, got ${JSON.stringify(rootRange)}.`,
|
|
]);
|
|
}
|
|
|
|
const failures = [];
|
|
let constrainedDependencies = 0;
|
|
|
|
for (const dependency of Object.keys(rootManifest.dependencies ?? {}).sort()) {
|
|
const manifestPath = join(
|
|
repositoryRoot,
|
|
'node_modules',
|
|
...dependency.split('/'),
|
|
'package.json',
|
|
);
|
|
let manifest;
|
|
try {
|
|
manifest = readManifest(manifestPath);
|
|
} catch (error) {
|
|
failures.push(
|
|
`cannot read installed manifest for ${dependency} at ${manifestPath}: ${String(error)}. ` +
|
|
'Run pnpm install before this check.',
|
|
);
|
|
continue;
|
|
}
|
|
|
|
const dependencyRange = manifest.engines?.node;
|
|
if (!dependencyRange) continue;
|
|
constrainedDependencies += 1;
|
|
const dependencyMinimum = semver.minVersion(dependencyRange);
|
|
if (dependencyMinimum === null) {
|
|
failures.push(
|
|
`${dependency} declares an invalid engines.node range: ${JSON.stringify(dependencyRange)}.`,
|
|
);
|
|
continue;
|
|
}
|
|
if (semver.lt(rootMinimum, dependencyMinimum)) {
|
|
failures.push(
|
|
`root engines.node ${JSON.stringify(rootRange)} starts at ${rootMinimum.version}, below ` +
|
|
`${dependency}@${manifest.version} engines.node ${JSON.stringify(dependencyRange)} ` +
|
|
`(minimum ${dependencyMinimum.version}).`,
|
|
);
|
|
}
|
|
}
|
|
|
|
if (failures.length > 0) {
|
|
fail('The root Node engine minimum is below its direct production dependencies:', failures);
|
|
}
|
|
|
|
console.log(
|
|
`Node engine contract passed: root minimum ${rootMinimum.version} satisfies ` +
|
|
`${constrainedDependencies} engine-constrained direct production dependencies.`,
|
|
);
|