import { readFile } from 'node:fs/promises'; import path from 'node:path'; import { fail, pass, repositoryRoot } from './lib.mjs'; const expected = { node: '24.17.0', pnpm: '11.9.0', }; const packageJson = JSON.parse(await readFile(path.join(repositoryRoot, 'package.json'), 'utf8')); const lockfile = await readFile(path.join(repositoryRoot, 'pnpm-lock.yaml'), 'utf8'); const nodeVersion = (await readFile(path.join(repositoryRoot, '.node-version'), 'utf8')).trim(); const nvmVersion = (await readFile(path.join(repositoryRoot, '.nvmrc'), 'utf8')).trim(); const errors = []; if (packageJson.packageManager !== `pnpm@${expected.pnpm}`) { errors.push(`packageManager must be pnpm@${expected.pnpm}.`); } if (packageJson.engines?.node !== expected.node) { errors.push(`package.json engines.node must be ${expected.node}.`); } if (packageJson.engines?.pnpm !== expected.pnpm) { errors.push(`package.json engines.pnpm must be ${expected.pnpm}.`); } if (nodeVersion !== expected.node || nvmVersion !== expected.node) { errors.push('.node-version and .nvmrc must match the approved Node.js runtime.'); } const directDependencies = { ...(packageJson.dependencies ?? {}), ...(packageJson.devDependencies ?? {}), }; const exactVersion = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/; for (const [name, version] of Object.entries(directDependencies)) { if (typeof version !== 'string' || !exactVersion.test(version)) { errors.push(`${name} must use an exact direct version, received ${String(version)}.`); continue; } const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const escapedVersion = version.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const lockSpecifier = new RegExp( `(?:^|\\n)\\s{6}['\"]?${escapedName}['\"]?:\\n\\s{8}specifier: ${escapedVersion}(?:\\n|$)`, ); if (!lockSpecifier.test(lockfile)) { errors.push( `${name}@${version} is not represented by an exact importer specifier in pnpm-lock.yaml.`, ); } } if (errors.length) fail(errors); else { pass( `Pinned Node ${expected.node}, pnpm ${expected.pnpm}, and ${Object.keys(directDependencies).length} exact direct dependency versions match the lockfile.`, ); }