Files
FootPrint/scripts/check.mjs
T

63 lines
2.6 KiB
JavaScript
Raw 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.
// 静态检查:语法 + 类型 + 构建 + 关键标记 tripwire(CI 与 pre-push 共用)
import { spawnSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
import url from 'node:url';
const root = path.resolve(path.dirname(url.fileURLToPath(import.meta.url)), '..');
let failures = 0;
const step = (label, fn) => {
process.stdout.write('==> ' + label + ' ... ');
try { fn(); console.log('OK'); }
catch (e) { console.log('FAIL\n' + String(e.message || e).slice(-2000)); failures++; }
};
// 1) 所有服务端 .mjs 语法检查(新增文件自动纳入)
const mjsDirs = ['sync-server/src', 'app/server', 'scripts'];
const mjsFiles = mjsDirs.flatMap((d) =>
fs.readdirSync(path.join(root, d)).filter((f) => f.endsWith('.mjs')).map((f) => path.join(d, f)));
step('node --check × ' + mjsFiles.length + ' 个文件', () => {
for (const f of mjsFiles) {
const r = spawnSync(process.execPath, ['--check', path.join(root, f)], { encoding: 'utf8' });
if (r.status !== 0) throw new Error(f + '\n' + r.stderr);
}
});
// 2) TypeScript 类型检查
const tsc = path.join(root, 'app/node_modules/typescript/bin/tsc');
if (fs.existsSync(tsc)) {
step('tsc --noEmit(前端类型)', () => {
const r = spawnSync(process.execPath, [tsc, '--noEmit'], { cwd: path.join(root, 'app'), encoding: 'utf8' });
if (r.status !== 0) throw new Error(r.stdout || r.stderr);
});
} else console.log('==> tsc 跳过(app/node_modules 不存在,先安装依赖)');
// 3) 前端构建(确保源码可构建;产物不提交)
const vite = path.join(root, 'app/node_modules/vite/bin/vite.js');
if (fs.existsSync(vite)) {
step('vite build', () => {
const r = spawnSync(process.execPath, [vite, 'build'], { cwd: path.join(root, 'app'), encoding: 'utf8' });
if (r.status !== 0) throw new Error(r.stdout || r.stderr);
});
} else console.log('==> vite 跳过(app/node_modules 不存在)');
// 4) 关键文件 tripwire:防止「改了没提交」类事故再次发生
step('关键标记 tripwire', () => {
const musts = [
['app/server/db.mjs', "case 'demo_seed'"],
['app/server/db.mjs', 'DEMO_ROWS'],
['app/public/sw.js', 'fp-static-v3'],
['sync-server/src/db.mjs', "name='remark'"],
['sync-server/src/index.mjs', 'demo_seed'],
];
for (const [f, needle] of musts) {
const p = path.join(root, f);
if (!fs.existsSync(p) || !fs.readFileSync(p, 'utf8').includes(needle)) {
throw new Error(f + ' 缺少关键标记: ' + needle);
}
}
});
if (failures) { console.error('\n✗ check 失败:' + failures + ' 项'); process.exit(1); }
console.log('\n✓ check 全部通过');