/** * 从 tools/module-tiers.json(编码规范 §4 层级表的机器形式)生成 depcruise 的 * tier-order 规则,写入 tools/depcruise-tiers.generated.cjs。 * * 规则语义(§5.2):模块只准 import §4 表中**层级更低**者的 index.ts; * 同层互不 import(协作走 port + app 装配),更高层当然也不行。 * * 运行:pnpm gen:tiers(gates 的第一步,产物入库,diff 即规则变更) */ import { readFileSync, writeFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import { dirname, join } from 'node:path'; const here = dirname(fileURLToPath(import.meta.url)); const tiersPath = join(here, 'module-tiers.json'); const outPath = join(here, 'depcruise-tiers.generated.cjs'); type TierTable = { tiers: Record }; const raw = readFileSync(tiersPath, 'utf8'); const table = JSON.parse(raw) as TierTable; const modulesBase = '^apps/api/src/modules'; /** 模块名 → 层级 */ const tierOf = new Map(); for (const [tier, modules] of Object.entries(table.tiers)) { for (const m of modules) { if (tierOf.has(m)) throw new Error(`模块 ${m} 在层级表中重复出现`); tierOf.set(m, Number(tier)); } } const allModules = [...tierOf.keys()].sort(); type Rule = { name: string; comment: string; severity: 'error'; from: { path: string }; to: { path: string }; }; const rules: Rule[] = []; for (const from of allModules) { const fromTier = tierOf.get(from)!; // 不得依赖的模块 = 同层其它模块 + 全部更高层模块 const forbidden = allModules.filter((to) => to !== from && tierOf.get(to)! >= fromTier); if (forbidden.length === 0) continue; rules.push({ name: `tier-order-${from}`, comment: `模块 ${from}(L${fromTier})只准依赖更低层级模块;` + `同层互需一律 port + app 装配(编码规范 §4 / §5.2)`, severity: 'error', from: { path: `${modulesBase}/${from}/` }, to: { path: `${modulesBase}/(${forbidden.join('|')})/` }, }); } // 未登记模块拦截:modules/ 下出现层级表里没有的目录即报错(§16 检查清单第一条) const knownGroup = allModules.join('|'); const banner = `/* eslint-disable */ /** * 本文件由 tools/gen-depcruise-tiers.ts 从 tools/module-tiers.json 生成。 * 请勿手改 —— 改层级请改 module-tiers.json 与 编码规范.md §4,然后 pnpm gen:tiers。 */ `; const body = banner + 'module.exports = ' + JSON.stringify( [ ...rules, { name: 'module-registered-in-tiers', comment: 'modules/ 下的每个模块必须登记在 tools/module-tiers.json(编码规范 §16)', severity: 'error', from: {}, to: { path: `${modulesBase}/([^/]+)/`, pathNot: `${modulesBase}/(${knownGroup})/`, }, }, ], null, 2, ) + ';\n'; writeFileSync(outPath, body, 'utf8'); process.stdout.write( `gen-depcruise-tiers: ${rules.length + 1} 条规则 → tools/depcruise-tiers.generated.cjs\n`, );