Files
谢宇宁andClaude Opus 5.5 f65d10e998 Initial commit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 23:07:59 +07:00

77 lines
3.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {existsSync, readFileSync} from 'node:fs';
import {createRequire} from 'node:module';
import {dirname, join, resolve} from 'node:path';
import {fileURLToPath} from 'node:url';
const root=resolve(dirname(fileURLToPath(import.meta.url)),'..');
/** Runtime packages that must match package-lock.json when building or deploying. */
export const LOCKED_RUNTIME=['next','react','react-dom','dotenv','hls.js','qrcode'];
export function packageLockVersions(rootDir=root) {
const lock=JSON.parse(readFileSync(join(rootDir,'package-lock.json'),'utf8'));
const versions={};
for(const name of LOCKED_RUNTIME){
const entry=lock.packages?.[`node_modules/${name}`];
if(!entry?.version)throw new Error(`package-lock.json 缺少 ${name}`);
versions[name]=entry.version;
}
return versions;
}
export function installedVersions(rootDir=root,names=LOCKED_RUNTIME) {
const require=createRequire(join(rootDir,'package.json'));
const versions={};
for(const name of names){
try{
versions[name]=require(`${name}/package.json`).version;
}catch{
throw new Error(`未安装 ${name},请先执行 npm ci 或 pnpm install`);
}
}
return versions;
}
/** Best-effort read of direct dependency versions from pnpm-lock.yaml importers. */
export function pnpmLockVersions(rootDir=root) {
const file=join(rootDir,'pnpm-lock.yaml');
if(!existsSync(file))return null;
const text=readFileSync(file,'utf8');
const versions={};
for(const name of LOCKED_RUNTIME){
const escaped=name.replace(/[.*+?^${}()|[\]\\]/g,'\\$&');
const match=text.match(new RegExp(`(?:^|\\n)\\s{6}${escaped}:\\n(?:\\s{8}.*\\n)*?\\s{8}version:\\s+(\\S+)`));
if(!match)throw new Error(`pnpm-lock.yaml 缺少 ${name}`);
versions[name]=match[1].replace(/\(.*$/,'');
}
return versions;
}
export function checkLockSync(rootDir=root) {
const expected=packageLockVersions(rootDir);
const installed=installedVersions(rootDir);
const mismatches=[];
for(const name of LOCKED_RUNTIME){
if(installed[name]!==expected[name])mismatches.push(`${name}: 已安装 ${installed[name]},package-lock.json 为 ${expected[name]}`);
}
const pnpm=pnpmLockVersions(rootDir);
if(pnpm){
for(const name of LOCKED_RUNTIME){
if(pnpm[name]!==expected[name])mismatches.push(`${name}: pnpm-lock.yaml 为 ${pnpm[name]},package-lock.json 为 ${expected[name]}`);
}
}
if(mismatches.length){
throw new Error(`依赖版本不一致(发版以 package-lock.json / npm ci 为准):\n- ${mismatches.join('\n- ')}\n请用同一版本同步:npm install 与 pnpm install,或将 next 等依赖钉死后再更新两份 lock。`);
}
return {expected,installed,pnpm};
}
if(process.argv[1]&&resolve(process.argv[1])===fileURLToPath(import.meta.url)) {
try {
const result=checkLockSync();
console.log(`lock sync ok (npm${result.pnpm?'+pnpm':''}): next@${result.expected.next}`);
}catch(error) {
console.error(error instanceof Error?error.message:error);
process.exitCode=1;
}
}