Initial commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
谢宇宁
2026-11-05 23:07:59 +07:00
co-authored by Claude Opus 5.5
commit f65d10e998
377 changed files with 31301 additions and 0 deletions
+76
View File
@@ -0,0 +1,76 @@
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;
}
}