From 21b9d437094577435840e8fb314247fa06d1ec7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B7=91=E5=A9=B7=E9=99=88?= Date: Mon, 9 Mar 2026 15:55:22 +0800 Subject: [PATCH] =?UTF-8?q?Step=206:=20=E5=A5=91=E7=BA=A6=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=E8=84=9A=E6=9C=AC=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/contract-check.js | 64 ++++++++++++++--------------- scripts/route-align-check.js | 78 +++++++++++++++++------------------- 2 files changed, 68 insertions(+), 74 deletions(-) diff --git a/scripts/contract-check.js b/scripts/contract-check.js index a988877d..f43be1b6 100644 --- a/scripts/contract-check.js +++ b/scripts/contract-check.js @@ -1,50 +1,50 @@ -// scripts/contract-check.js -// 用途:确保每个 HLI 路由文件都有对应的 JSON Schema 且路径一致 - +// 用途:确保每个 HLI 路由文件都有对应的 JSON Schema 且格式合法 const fs = require('fs'); const path = require('path'); -const glob = require('glob'); const ROUTE_DIR = 'src/routes/hli'; const SCHEMA_DIR = 'src/schemas/hli'; - -// 扫描所有 HLI 路由文件 -const routeFiles = glob.sync(`${ROUTE_DIR}/**/*.js`); const errors = []; -routeFiles.forEach(routeFile => { - const domain = path.basename(path.dirname(routeFile)); - const name = path.basename(routeFile, '.js'); +// 获取所有业务域目录 +const domains = fs.readdirSync(ROUTE_DIR).filter(f => { + return fs.statSync(path.join(ROUTE_DIR, f)).isDirectory(); +}); - // 跳过 index.js(路由注册中心,无需 schema) - if (name === 'index') return; +domains.forEach(domain => { + const routeDir = path.join(ROUTE_DIR, domain); + const schemaDir = path.join(SCHEMA_DIR, domain); - const schemaPath = path.join(SCHEMA_DIR, domain, `${name}.schema.json`); - - // 检查1: 对应 schema 文件是否存在 - if (!fs.existsSync(schemaPath)) { - errors.push(`❌ [MISSING SCHEMA] ${routeFile} → 缺少 ${schemaPath}`); - return; - } - - // 检查2: schema 文件格式是否合法 - try { - const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf8')); - if (!schema.input || !schema.output) { - errors.push(`❌ [INVALID SCHEMA] ${schemaPath} → 缺少 input/output 定义`); + // 扫描路由文件 + const routeFiles = fs.readdirSync(routeDir).filter(f => f.endsWith('.js')); + + routeFiles.forEach(routeFile => { + const name = path.basename(routeFile, '.js'); + const schemaPath = path.join(schemaDir, name + '.schema.json'); + + if (!fs.existsSync(schemaPath)) { + errors.push('❌ [MISSING] ' + routeFile + ' → 缺少 ' + schemaPath); + return; } - if (!schema.hli_id) { - errors.push(`❌ [MISSING HLI_ID] ${schemaPath} → 缺少 hli_id 字段`); + + try { + const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf8')); + if (!schema.input || !schema.output) { + errors.push('❌ [INVALID] ' + schemaPath + ' → 缺少 input/output'); + } + if (!schema.hli_id) { + errors.push('❌ [NO ID] ' + schemaPath + ' → 缺少 hli_id'); + } + } catch (e) { + errors.push('❌ [PARSE] ' + schemaPath + ' → ' + e.message); } - } catch (e) { - errors.push(`❌ [PARSE ERROR] ${schemaPath} → ${e.message}`); - } + }); }); if (errors.length > 0) { - console.error('\n🚫 HLI Contract Check FAILED:\n'); + console.error('\n❌ HLI Contract Check FAILED:\n'); errors.forEach(e => console.error(e)); process.exit(1); } else { - console.log('✅ HLI Contract Check PASSED — 所有路由均有合法 schema'); + console.log('✅ HLI Contract Check PASSED'); } diff --git a/scripts/route-align-check.js b/scripts/route-align-check.js index 06ccfbfe..34bce860 100644 --- a/scripts/route-align-check.js +++ b/scripts/route-align-check.js @@ -1,64 +1,58 @@ -// scripts/route-align-check.js -// 用途:检查路由路径与 HLI 注册表编号的一致性 - +// 用途:检查 HLI 注册表里的 17 个接口,代码里实现了几个 const fs = require('fs'); const path = require('path'); -// HLI 路由路径映射(从 Notion 注册表同步) const HLI_ROUTES = { - 'HLI-AUTH-001': '/hli/auth/login', - 'HLI-AUTH-002': '/hli/auth/register', - 'HLI-AUTH-003': '/hli/auth/verify', - 'HLI-PERSONA-001': '/hli/persona/load', - 'HLI-PERSONA-002': '/hli/persona/switch', - 'HLI-USER-001': '/hli/user/profile', - 'HLI-USER-002': '/hli/user/profile/update', - 'HLI-TICKET-001': '/hli/ticket/create', - 'HLI-TICKET-002': '/hli/ticket/query', - 'HLI-TICKET-003': '/hli/ticket/status', - 'HLI-DIALOGUE-001': '/hli/dialogue/send', - 'HLI-DIALOGUE-002': '/hli/dialogue/stream', - 'HLI-DIALOGUE-003': '/hli/dialogue/history', - 'HLI-STORAGE-001': '/hli/storage/upload', - 'HLI-STORAGE-002': '/hli/storage/download', + 'HLI-AUTH-001': '/hli/auth/login', + 'HLI-AUTH-002': '/hli/auth/register', + 'HLI-AUTH-003': '/hli/auth/verify', + 'HLI-PERSONA-001': '/hli/persona/load', + 'HLI-PERSONA-002': '/hli/persona/switch', + 'HLI-USER-001': '/hli/user/profile', + 'HLI-USER-002': '/hli/user/profile/update', + 'HLI-TICKET-001': '/hli/ticket/create', + 'HLI-TICKET-002': '/hli/ticket/query', + 'HLI-TICKET-003': '/hli/ticket/status', + 'HLI-DIALOGUE-001': '/hli/dialogue/send', + 'HLI-DIALOGUE-002': '/hli/dialogue/stream', + 'HLI-DIALOGUE-003': '/hli/dialogue/history', + 'HLI-STORAGE-001': '/hli/storage/upload', + 'HLI-STORAGE-002': '/hli/storage/download', 'HLI-DASHBOARD-001': '/hli/dashboard/status', - 'HLI-DASHBOARD-002': '/hli/dashboard/realtime', + 'HLI-DASHBOARD-002': '/hli/dashboard/realtime' }; const schemaDir = 'src/schemas/hli'; -const errors = []; +let implemented = 0; +let missing = 0; -Object.entries(HLI_ROUTES).forEach(([hliId, expectedPath]) => { +Object.entries(HLI_ROUTES).forEach(([hliId, route]) => { const domain = hliId.split('-')[1].toLowerCase(); const domainDir = path.join(schemaDir, domain); - - // 若 domain 目录尚不存在,视为未实现 + if (!fs.existsSync(domainDir)) { - errors.push(`⚠️ [UNIMPLEMENTED] ${hliId} (${expectedPath}) — 尚无 schema 文件`); + console.warn('△ [UNIMPLEMENTED] ' + hliId + ' (' + route + ')'); + missing++; return; } - - const schemaFiles = fs.readdirSync(domainDir).filter(f => f.endsWith('.schema.json')); - - const matched = schemaFiles.find(f => { + + const files = fs.readdirSync(domainDir).filter(f => f.endsWith('.schema.json')); + const found = files.some(f => { try { const schema = JSON.parse(fs.readFileSync(path.join(domainDir, f), 'utf8')); return schema.hli_id === hliId; - } catch (_) { - return false; - } + } catch { return false; } }); - - if (!matched) { - errors.push(`⚠️ [UNIMPLEMENTED] ${hliId} (${expectedPath}) — 尚无 schema 文件`); + + if (found) { + implemented++; + } else { + console.warn('△ [UNIMPLEMENTED] ' + hliId + ' (' + route + ')'); + missing++; } }); -if (errors.length > 0) { - console.warn('\n⚠️ Route Alignment Report:\n'); - errors.forEach(e => console.warn(e)); - // 非阻断,仅报告 - console.warn(`\n📊 覆盖率: ${Object.keys(HLI_ROUTES).length - errors.length}/${Object.keys(HLI_ROUTES).length}`); -} else { - console.log('✅ Route Alignment PASSED — 所有 HLI 接口均已实现'); +console.log(`\n\n📊 覆盖率: ${implemented} / ${implemented + missing}`); +if (missing === 0) { + console.log('✅ Route Alignment PASSED - 所有 HLI 接口均已实现'); }