/** * T38 第二轮:改动文件的编译/导入自检(票 38 复验反馈)。 * * 只做两件事:① 三个 .vue 能被 @vue/compiler-sfc 解析并编译 script+template; * ② 三个改过的 .js 能被 node 真实 import(导出面完整、无语法错)。 * 不启动 dev server、不控制浏览器(AGENTS.md 的验证纪律)。 */ import { readFileSync } from 'node:fs' import { parse, compileScript, compileTemplate } from 'vue/compiler-sfc' const ROOT = new URL('../../../', import.meta.url) const VUES = ['src/modules/cockpit/components/PanelBlocks.vue', 'src/modules/cockpit/CockpitShell.vue'] let failed = 0 for (const rel of VUES) { const source = readFileSync(new URL(rel, ROOT), 'utf8') const { descriptor, errors } = parse(source, { filename: rel }) if (errors.length) { console.log(`FAIL parse ${rel} — ${errors[0].message}`) failed += 1 continue } try { compileScript(descriptor, { id: rel }) const tpl = compileTemplate({ source: descriptor.template.content, filename: rel, id: rel }) if (tpl.errors.length) throw new Error(tpl.errors[0]) console.log(`PASS compile ${rel}`) } catch (error) { console.log(`FAIL compile ${rel} — ${error.message}`) failed += 1 } } for (const rel of [ 'src/modules/cockpit/domain/mapLocate.js', 'src/modules/cockpit/domain/overviewPanels.js', 'src/modules/cockpit/stores/overviewStore.js', 'src/modules/cockpit/stores/infrastructureStore.js', ]) { try { await import(new URL(rel, ROOT).href) console.log(`PASS import ${rel}`) } catch (error) { console.log(`FAIL import ${rel} — ${error.message}`) failed += 1 } } // 回联入口必须真的被 planLocate 用到(不是导出了没人调)。 const locate = readFileSync(new URL('src/modules/cockpit/domain/mapLocate.js', ROOT), 'utf8') const planBody = locate.slice(locate.indexOf('export function planLocate')) if (/findDeviceOwner\(objects, code\)/.test(planBody)) console.log('PASS 回联挂在 planLocate 判定链上') else { console.log('FAIL planLocate 没有调用 findDeviceOwner(回联是死导出)') failed += 1 } console.log('') console.log(failed ? `T38 round-2 compile check: ${failed} FAILED` : 'T38 round-2 compile check: all passed') if (failed) process.exit(1)