#!/usr/bin/env node /** * NestJS vs Java 路由规范化对比脚本 * 解决参数风格差异、空子路径、模块分组等问题 */ const fs = require('fs'); const path = require('path'); const glob = require('glob'); // 路由规范化函数 function normalizeRoute(route) { return route .replace(/:([^/]+)/g, '{$1}') // :param -> {param} .replace(/\/$/g, '') // 移除尾部斜杠 .replace(/^\/$/, ''); // 处理根路径 } // 提取NestJS路由信息 function extractNestJSRoutes(controllerPath) { const content = fs.readFileSync(controllerPath, 'utf8'); const routes = []; // 提取类级Controller路径 const controllerMatch = content.match(/@Controller\(["'`]([^"'`]+)["'`]\)/); const basePath = controllerMatch ? controllerMatch[1] : ''; // 提取方法级路由 const methodMatches = content.matchAll(/@(Get|Post|Put|Delete|Patch)\((["'`]([^"'`]*)["'`])?\)[\s\S]*?(async\s+)?(\w+)\s*\(/g); for (const match of methodMatches) { const method = match[1].toUpperCase(); const subPath = match[3] || ''; const fullPath = normalizeRoute(path.join(basePath, subPath)); routes.push({ method, path: fullPath, basePath, subPath, file: path.basename(controllerPath) }); } return routes; } // 提取Java路由信息 function extractJavaRoutes(controllerPath) { const content = fs.readFileSync(controllerPath, 'utf8'); const routes = []; // 提取类级RequestMapping路径 const classMappingMatch = content.match(/@RequestMapping\(["'`]([^"'`]+)["'`]\)/); const basePath = classMappingMatch ? classMappingMatch[1] : ''; // 提取方法级路由 const methodMatches = content.matchAll(/@(GetMapping|PostMapping|PutMapping|DeleteMapping|RequestMapping)\((["'`]([^"'`]*)["'`])?\)[\s\S]*?(\w+)\s*\(/g); for (const match of methodMatches) { const annotation = match[1]; const subPath = match[3] || ''; let method = 'GET'; if (annotation === 'PostMapping') method = 'POST'; else if (annotation === 'PutMapping') method = 'PUT'; else if (annotation === 'DeleteMapping') method = 'DELETE'; const fullPath = normalizeRoute(path.join(basePath, subPath)); routes.push({ method, path: fullPath, basePath, subPath, file: path.basename(controllerPath) }); } return routes; } // 主对比函数 function compareRoutes(nestDir, javaDir) { const nestRoutes = []; const javaRoutes = []; // 提取NestJS路由 const nestFiles = glob.sync(`${nestDir}/**/*.controller.ts`); nestFiles.forEach(file => { const routes = extractNestJSRoutes(file); nestRoutes.push(...routes); }); // 提取Java路由 const javaFiles = glob.sync(`${javaDir}/**/*Controller.java`); javaFiles.forEach(file => { const routes = extractJavaRoutes(file); javaRoutes.push(...routes); }); // 对比分析 const comparison = { total: { nest: nestRoutes.length, java: javaRoutes.length }, matches: [], missingInNest: [], missingInJava: [], inconsistencies: [] }; // 标准化路由键用于对比 const getRouteKey = (route) => `${route.method}:${route.path}`; const nestRouteMap = new Map(nestRoutes.map(r => [getRouteKey(r), r])); const javaRouteMap = new Map(javaRoutes.map(r => [getRouteKey(r), r])); // 查找匹配项 for (const [key, nestRoute] of nestRouteMap) { if (javaRouteMap.has(key)) { comparison.matches.push({ route: key, nestFile: nestRoute.file, javaFile: javaRouteMap.get(key).file }); } else { comparison.missingInJava.push(nestRoute); } } // 查找Java中缺失的项 for (const [key, javaRoute] of javaRouteMap) { if (!nestRouteMap.has(key)) { comparison.missingInNest.push(javaRoute); } } return comparison; } // 执行对比 console.log('🚀 NestJS vs Java 路由规范化对比开始...\n'); const nestDir = '/Users/wanwu/Documents/wanwujie/wwjcloud-nsetjs/wwjcloud-nest-v1/wwjcloud/libs/wwjcloud-core/src/controllers'; const javaDir = '/Users/wanwu/Documents/wanwujie/wwjcloud-nsetjs/niucloud-java/niucloud-core/src/main/java/com/niu/core/controller'; const result = compareRoutes(nestDir, javaDir); console.log('📊 对比结果:'); console.log(`✅ 匹配路由: ${result.matches.length}`); console.log(`❌ NestJS缺失: ${result.missingInNest.length}`); console.log(`⚠️ Java缺失: ${result.missingInJava.length}`); console.log(`📈 覆盖率: ${((result.matches.length / result.total.java) * 100).toFixed(1)}%`); if (result.missingInNest.length > 0) { console.log('\n🔍 NestJS缺失路由详情:'); result.missingInNest.forEach(route => { console.log(` ${route.method} ${route.path} (${route.file})`); }); } if (result.missingInJava.length > 0) { console.log('\n🔍 Java缺失路由详情:'); result.missingInJava.forEach(route => { console.log(` ${route.method} ${route.path} (${route.file})`); }); } console.log('\n✅ 对比完成!');