fix: 恢复原始迁移工具 - 删除所有enhanced文件

🗑️  删除的文件:
- enhanced-migration-coordinator.js
- enhanced-business-logic-converter.js
- enhanced-dependency-injection-converter.js
- ENHANCED_MIGRATION_REPORT.json

 恢复的文件:
- migration-coordinator.js(从git历史恢复)

🎯 原始工具架构:
- 1个主协调器(migration-coordinator.js)
- 7个层级生成器(controller, service, entity, dto, enum, listener, job)
- 已支持保持Java子目录结构
This commit is contained in:
wanwu
2025-10-28 15:53:21 +08:00
parent 157dba3994
commit be792c9735
4 changed files with 365 additions and 898 deletions

View File

@@ -1,25 +0,0 @@
{
"summary": {
"totalTime": -1761637480243,
"filesProcessed": 1215,
"servicesGenerated": 158,
"typesGenerated": 629,
"successRate": "100.0%",
"errors": 0
},
"details": {
"diStats": {
"description": "依赖注入推断统计",
"note": "已集成增强的DI转换器"
},
"businessLogicStats": {
"description": "业务逻辑转换统计",
"note": "已集成增强的业务逻辑转换器"
},
"dtoStats": {
"description": "DTO生成统计",
"generated": 629
}
},
"errors": []
}

View File

@@ -1,436 +0,0 @@
const fs = require('fs');
const path = require('path');
const NamingUtils = require('../utils/naming-utils');
/**
* 增强的业务逻辑转换器
* 核心能力:
* 1. QueryWrapper -> TypeORM QueryBuilder
* 2. Mapper.xxx() -> Repository.xxx()
* 3. Stream API -> Array methods
* 4. Java Utils -> wwjcloud-boot services
* 5. Lambda -> Arrow functions
*/
class EnhancedBusinessLogicConverter {
constructor() {
this.namingUtils = new NamingUtils();
// Mapper 方法映射到 Repository 方法
this.mapperMethodMapping = {
'selectById': 'findOne',
'selectOne': 'findOne',
'selectList': 'find',
'selectPage': 'findAndCount',
'insert': 'save',
'update': 'update',
'updateById': 'update',
'delete': 'delete',
'deleteById': 'delete',
'count': 'count'
};
// Java 工具类方法映射
this.utilsMethodMapping = {
'RequestUtils.getCurrentSiteId': 'this.requestContext.getSiteId',
'RequestUtils.getCurrentUserId': 'this.requestContext.getUserId',
'StringUtil.isEmpty': '!',
'StringUtil.isNotEmpty': '!!',
'ObjectUtil.isEmpty': '!',
'ObjectUtil.isNotEmpty': '!!',
'CollUtil.isEmpty': '!',
'CollUtil.isNotEmpty': '!!',
'DateUtil.now': 'new Date',
'DateUtil.format': 'DateUtils.format',
'FileUtils.upload': 'await this.fileUtils.upload',
'BeanUtils.copyProperties': 'Object.assign'
};
}
/**
* 主转换方法:转换完整的方法体
*/
convertMethodBody(javaMethod) {
if (!javaMethod.body) {
return ' // TODO: 实现业务逻辑\n throw new Error("Not implemented");';
}
let body = javaMethod.body;
// 应用所有转换规则
body = this.convertQueryWrapper(body);
body = this.convertMapperCalls(body);
body = this.convertStreamAPI(body);
body = this.convertUtilsCalls(body);
body = this.convertLambdaExpressions(body);
body = this.convertLogStatements(body);
body = this.convertExceptionHandling(body);
body = this.convertVariableDeclarations(body);
body = this.addAwaitToAsyncCalls(body);
return body;
}
/**
* 1. 转换 QueryWrapper
* 例new QueryWrapper<>().eq("id", id)
* -> this.repository.createQueryBuilder().where("id = :id", { id })
*/
convertQueryWrapper(body) {
// 匹配 QueryWrapper 创建和链式调用
const queryWrapperPattern = /new\s+QueryWrapper<[^>]*>\(\)([\s\S]*?)(?=;)/g;
body = body.replace(queryWrapperPattern, (match, chainCalls) => {
// 解析链式调用
const conditions = [];
// .eq(field, value)
const eqPattern = /\.eq\("([^"]+)",\s*([^)]+)\)/g;
let eqMatch;
while ((eqMatch = eqPattern.exec(chainCalls)) !== null) {
const field = eqMatch[1];
const value = eqMatch[2];
conditions.push(`${field} = :${field}`);
}
// .ne(field, value)
const nePattern = /\.ne\("([^"]+)",\s*([^)]+)\)/g;
let neMatch;
while ((neMatch = nePattern.exec(chainCalls)) !== null) {
const field = neMatch[1];
conditions.push(`${field} != :${field}`);
}
// .like(field, value)
const likePattern = /\.like\("([^"]+)",\s*([^)]+)\)/g;
let likeMatch;
while ((likeMatch = likePattern.exec(chainCalls)) !== null) {
const field = likeMatch[1];
conditions.push(`${field} LIKE :${field}`);
}
// .in(field, values)
const inPattern = /\.in\("([^"]+)",\s*([^)]+)\)/g;
let inMatch;
while ((inMatch = inPattern.exec(chainCalls)) !== null) {
const field = inMatch[1];
conditions.push(`${field} IN (:...${field})`);
}
// .orderByAsc(field) / .orderByDesc(field)
let orderBy = '';
if (chainCalls.includes('.orderByAsc')) {
const orderMatch = chainCalls.match(/\.orderByAsc\("([^"]+)"\)/);
if (orderMatch) {
orderBy = `.orderBy("${orderMatch[1]}", "ASC")`;
}
} else if (chainCalls.includes('.orderByDesc')) {
const orderMatch = chainCalls.match(/\.orderByDesc\("([^"]+)"\)/);
if (orderMatch) {
orderBy = `.orderBy("${orderMatch[1]}", "DESC")`;
}
}
// 生成 QueryBuilder
const whereClause = conditions.join(' AND ');
return `this.repository.createQueryBuilder().where("${whereClause}")${orderBy}`;
});
return body;
}
/**
* 2. 转换 Mapper 调用
* 例xxxMapper.selectById(id) -> await this.xxxRepository.findOne({ where: { id } })
*/
convertMapperCalls(body) {
// 匹配 Mapper 方法调用
const mapperPattern = /(\w+)Mapper\.(\w+)\(([^)]*)\)/g;
body = body.replace(mapperPattern, (match, mapperName, methodName, args) => {
const entityName = mapperName; // SysUser
const repositoryName = mapperName.charAt(0).toLowerCase() + mapperName.slice(1) + 'Repository';
// 根据方法名转换
switch (methodName) {
case 'selectById':
return `await this.${repositoryName}.findOne({ where: { id: ${args} } })`;
case 'selectOne':
// selectOne(queryWrapper) -> findOne(where)
return `await this.${repositoryName}.findOne({ where: ${args} })`;
case 'selectList':
// selectList(queryWrapper) -> find(where)
if (args.includes('QueryWrapper')) {
return `await this.${repositoryName}.find()`;
}
return `await this.${repositoryName}.find({ where: ${args} })`;
case 'selectPage':
// selectPage(page, queryWrapper) -> findAndCount
return `await this.${repositoryName}.findAndCount({ skip: (page - 1) * limit, take: limit })`;
case 'insert':
return `await this.${repositoryName}.save(${args})`;
case 'updateById':
// updateById(entity) -> update(id, data)
return `await this.${repositoryName}.update(${args}.id, ${args})`;
case 'update':
// update(entity, queryWrapper) -> update
return `await this.${repositoryName}.update(${args})`;
case 'deleteById':
return `await this.${repositoryName}.delete(${args})`;
case 'delete':
return `await this.${repositoryName}.delete(${args})`;
case 'count':
if (args.includes('QueryWrapper')) {
return `await this.${repositoryName}.count()`;
}
return `await this.${repositoryName}.count({ where: ${args} })`;
default:
return `await this.${repositoryName}.${methodName}(${args})`;
}
});
return body;
}
/**
* 3. 转换 Stream API
* 例list.stream().map(x -> x.getName()).collect(Collectors.toList())
* -> list.map(x => x.name)
*/
convertStreamAPI(body) {
// .stream().map().collect(Collectors.toList())
body = body.replace(/(\w+)\.stream\(\)\.map\(([^)]+)\)\.collect\(Collectors\.toList\(\)\)/g,
'$1.map($2)');
// .stream().filter().collect()
body = body.replace(/(\w+)\.stream\(\)\.filter\(([^)]+)\)\.collect\(Collectors\.toList\(\)\)/g,
'$1.filter($2)');
// .stream().collect(Collectors.toList())
body = body.replace(/\.stream\(\)\.collect\(Collectors\.toList\(\)\)/g, '');
// .stream().collect(Collectors.toSet())
body = body.replace(/\.stream\(\)\.collect\(Collectors\.toSet\(\)\)/g, '');
// .stream().forEach(x -> ...)
body = body.replace(/\.stream\(\)\.forEach\(/g, '.forEach(');
return body;
}
/**
* 4. 转换工具类调用
*/
convertUtilsCalls(body) {
// 遍历所有工具类方法映射
for (const [javaCall, nestCall] of Object.entries(this.utilsMethodMapping)) {
const pattern = new RegExp(javaCall.replace(/\./g, '\\.'), 'g');
body = body.replace(pattern, nestCall);
}
// 特殊处理BeanUtils.copyProperties(source, target)
body = body.replace(/BeanUtils\.copyProperties\(([^,]+),\s*([^)]+)\)/g,
'Object.assign($2, $1)');
// Assert.notNull -> if (!xxx) throw
body = body.replace(/Assert\.notNull\(([^,]+),\s*"([^"]+)"\)/g,
'if (!$1) throw new BadRequestException("$2")');
// Assert.isTrue -> if (!xxx) throw
body = body.replace(/Assert\.isTrue\(([^,]+),\s*"([^"]+)"\)/g,
'if (!($1)) throw new BadRequestException("$2")');
return body;
}
/**
* 5. 转换 Lambda 表达式
* 例x -> x.getName() -> x => x.name
*/
convertLambdaExpressions(body) {
// 单参数 lambda: x -> ...
body = body.replace(/(\w+)\s*->\s*/g, '$1 => ');
// 多参数 lambda: (x, y) -> ...
body = body.replace(/\(([^)]+)\)\s*->\s*/g, '($1) => ');
// Java getter: x.getName() -> x.name
body = body.replace(/\.get(\w+)\(\)/g, (match, propName) => {
return '.' + propName.charAt(0).toLowerCase() + propName.slice(1);
});
return body;
}
/**
* 6. 转换日志语句
* 例log.info(...) -> this.logger.log(...)
*/
convertLogStatements(body) {
body = body.replace(/\blog\.info\(/g, 'this.logger.log(');
body = body.replace(/\blog\.error\(/g, 'this.logger.error(');
body = body.replace(/\blog\.warn\(/g, 'this.logger.warn(');
body = body.replace(/\blog\.debug\(/g, 'this.logger.debug(');
// logger.info -> this.logger.log
body = body.replace(/\blogger\.info\(/g, 'this.logger.log(');
return body;
}
/**
* 7. 转换异常处理
* 例throw new RuntimeException(...) -> throw new Error(...)
*/
convertExceptionHandling(body) {
// RuntimeException -> Error
body = body.replace(/throw\s+new\s+RuntimeException\(/g, 'throw new Error(');
// IllegalArgumentException -> BadRequestException
body = body.replace(/throw\s+new\s+IllegalArgumentException\(/g, 'throw new BadRequestException(');
// NullPointerException -> Error
body = body.replace(/throw\s+new\s+NullPointerException\(/g, 'throw new Error(');
// try-catch
body = body.replace(/catch\s*\(\s*Exception\s+e\s*\)/g, 'catch (e)');
body = body.replace(/catch\s*\(\s*(\w+Exception)\s+e\s*\)/g, 'catch (e)');
return body;
}
/**
* 8. 转换变量声明
* 例String name = ... -> const name: string = ...
*/
convertVariableDeclarations(body) {
// String/Integer/Long/Boolean -> const
body = body.replace(/\b(String|Integer|Long|Boolean|Double|Float)\s+(\w+)\s*=/g, 'const $2: string =');
// List<T> -> const xxx: T[] =
body = body.replace(/List<([^>]+)>\s+(\w+)\s*=/g, 'const $2: $1[] =');
// Map<K,V> -> const xxx: Map<K,V> =
body = body.replace(/Map<([^>]+)>\s+(\w+)\s*=/g, 'const $2: any =');
// new ArrayList<>() -> []
body = body.replace(/new\s+ArrayList<[^>]*>\(\)/g, '[]');
// new HashMap<>() -> {}
body = body.replace(/new\s+HashMap<[^>]*>\(\)/g, '{}');
// new HashSet<>() -> new Set()
body = body.replace(/new\s+HashSet<[^>]*>\(\)/g, 'new Set()');
return body;
}
/**
* 9. 为异步调用添加 await
*/
addAwaitToAsyncCalls(body) {
// 为 Repository 调用添加 await
body = body.replace(/(\s+)(this\.\w+Repository\.\w+\()/g, '$1await $2');
// 避免重复的 await await
body = body.replace(/await\s+await/g, 'await');
return body;
}
/**
* 10. 转换分页逻辑
* 例IPage<User> page = xxxMapper.selectPage(...)
* -> const [data, total] = await this.repository.findAndCount(...)
*/
convertPaginationLogic(body) {
// IPage<T> page = mapper.selectPage(...)
body = body.replace(
/IPage<([^>]+)>\s+(\w+)\s*=\s*(\w+)Mapper\.selectPage\(([^)]+)\)/g,
'const [data, total] = await this.$3Repository.findAndCount({ skip: ($4 - 1) * limit, take: limit })'
);
// page.getRecords() -> data
body = body.replace(/(\w+)\.getRecords\(\)/g, 'data');
// page.getTotal() -> total
body = body.replace(/(\w+)\.getTotal\(\)/g, 'total');
return body;
}
/**
* 完整转换方法(包含所有步骤)
*/
convertFullMethod(javaMethod) {
if (!javaMethod.body) {
return {
body: ' // TODO: 实现业务逻辑\n throw new Error("Not implemented");',
hasBusinessLogic: false
};
}
let body = javaMethod.body;
const originalBody = body;
// 应用所有转换
body = this.convertQueryWrapper(body);
body = this.convertMapperCalls(body);
body = this.convertStreamAPI(body);
body = this.convertUtilsCalls(body);
body = this.convertLambdaExpressions(body);
body = this.convertLogStatements(body);
body = this.convertExceptionHandling(body);
body = this.convertVariableDeclarations(body);
body = this.convertPaginationLogic(body);
body = this.addAwaitToAsyncCalls(body);
// 计算转换质量
const quality = this.assessConversionQuality(originalBody, body);
return {
body,
hasBusinessLogic: true,
quality,
stats: {
queryWrapperConverted: (originalBody.match(/QueryWrapper/g) || []).length,
mapperCallsConverted: (originalBody.match(/Mapper\./g) || []).length,
streamAPIConverted: (originalBody.match(/\.stream\(\)/g) || []).length,
utilsCallsConverted: (originalBody.match(/(StringUtil|ObjectUtil|CollUtil|RequestUtils)\./g) || []).length
}
};
}
/**
* 评估转换质量
*/
assessConversionQuality(original, converted) {
const issues = [];
// 检查是否还有 Java 语法残留
if (converted.includes('QueryWrapper')) issues.push('QueryWrapper 未完全转换');
if (converted.includes('Mapper.')) issues.push('Mapper 调用未完全转换');
if (converted.includes('.stream()')) issues.push('Stream API 未完全转换');
if (converted.includes('StringUtil.')) issues.push('StringUtil 未完全转换');
if (converted.includes('->')) issues.push('Lambda 表达式未完全转换');
if (converted.includes('log.')) issues.push('日志语句未完全转换');
return {
isComplete: issues.length === 0,
issues,
score: Math.max(0, 100 - issues.length * 10)
};
}
}
module.exports = EnhancedBusinessLogicConverter;

View File

@@ -1,437 +0,0 @@
const fs = require('fs');
const path = require('path');
const NamingUtils = require('../utils/naming-utils');
/**
* 增强的依赖注入转换器
* 核心能力:
* 1. 分析方法体,智能推断所需依赖
* 2. 自动映射 Mapper -> Repository
* 3. 自动映射 Java Utils -> wwjcloud-boot 服务
* 4. 推断 Service 间依赖关系
*/
class EnhancedDependencyInjectionConverter {
constructor() {
this.namingUtils = new NamingUtils();
// Java Utils -> wwjcloud-boot 服务映射
this.utilsServiceMapping = {
'RequestUtils': 'RequestContextService',
'RedisUtils': 'CacheService',
'JwtUtil': 'JwtService',
'FileUtil': 'FileUtils',
'DateUtil': 'DateUtils',
'StringUtil': 'StringUtils',
'ObjectUtil': 'CommonUtils'
};
}
/**
* 智能推断依赖(核心方法)
*/
inferDependencies(javaClass) {
const dependencies = new Map(); // 使用 Map 避免重复
// 1. 提取显式声明的依赖(@Autowired/@Resource
this.extractExplicitDependencies(javaClass, dependencies);
// 2. 分析方法体,推断 Mapper -> Repository
this.inferRepositoryDependencies(javaClass, dependencies);
// 3. 分析方法体,推断 Service 依赖
this.inferServiceDependencies(javaClass, dependencies);
// 4. 分析方法体,推断 Utils -> wwjcloud-boot 服务
this.inferUtilsServiceDependencies(javaClass, dependencies);
// 5. 自动添加 Logger
this.addLoggerDependency(javaClass, dependencies);
return Array.from(dependencies.values());
}
/**
* 1. 提取显式声明的依赖
*/
extractExplicitDependencies(javaClass, dependencies) {
if (!javaClass.fields) return;
javaClass.fields.forEach(field => {
if (field.annotations && (
field.annotations.includes('@Autowired') ||
field.annotations.includes('@Resource')
)) {
const key = field.name;
if (!dependencies.has(key)) {
dependencies.set(key, {
source: 'explicit',
name: field.name,
javaType: field.type,
nestType: this.mapJavaTypeToNestType(field.type),
injectionType: this.determineInjectionType(field.type)
});
}
}
});
}
/**
* 2. 推断 Repository 依赖
* 分析xxxMapper.selectById() -> @InjectRepository(Entity)
*/
inferRepositoryDependencies(javaClass, dependencies) {
if (!javaClass.methods) return;
javaClass.methods.forEach(method => {
if (!method.body) return;
// 匹配 xxxMapper.xxx() 调用
const mapperPattern = /(\w+Mapper)\.(\w+)\(/g;
let match;
while ((match = mapperPattern.exec(method.body)) !== null) {
const mapperName = match[1]; // 例如: SysUserMapper
const mapperField = mapperName.charAt(0).toLowerCase() + mapperName.slice(1);
// 转换为 Entity 名称
const entityName = mapperName.replace('Mapper', ''); // SysUser
const key = mapperField;
if (!dependencies.has(key)) {
dependencies.set(key, {
source: 'inferred-repository',
name: mapperField, // sysUserMapper
javaType: mapperName, // SysUserMapper
nestType: `Repository<${entityName}>`, // Repository<SysUser>
entityName: entityName,
injectionType: 'repository'
});
}
}
});
}
/**
* 3. 推断 Service 依赖
* 分析this.xxxService.xxx() 或 xxxService.xxx()
*/
inferServiceDependencies(javaClass, dependencies) {
if (!javaClass.methods) return;
javaClass.methods.forEach(method => {
if (!method.body) return;
// 匹配 Service 调用
const servicePattern = /(?:this\.)?(\w+Service)\.(\w+)\(/g;
let match;
while ((match = servicePattern.exec(method.body)) !== null) {
const serviceType = match[1]; // 例如: SysUserService
const serviceField = serviceType.charAt(0).toLowerCase() + serviceType.slice(1);
const key = serviceField;
if (!dependencies.has(key)) {
dependencies.set(key, {
source: 'inferred-service',
name: serviceField, // sysUserService
javaType: serviceType, // SysUserService
nestType: this.convertServiceName(serviceType), // SysUserServiceImplService
injectionType: 'service'
});
}
}
});
}
/**
* 4. 推断 Utils -> wwjcloud-boot 服务依赖
* 分析RequestUtils.xxx() -> RequestContextService
*/
inferUtilsServiceDependencies(javaClass, dependencies) {
if (!javaClass.methods) return;
javaClass.methods.forEach(method => {
if (!method.body) return;
// 检查每种 Utils 的使用
for (const [javaUtil, nestService] of Object.entries(this.utilsServiceMapping)) {
if (method.body.includes(javaUtil + '.')) {
const serviceField = nestService.charAt(0).toLowerCase() + nestService.slice(1);
const key = serviceField;
if (!dependencies.has(key)) {
dependencies.set(key, {
source: 'inferred-utils',
name: serviceField,
javaType: javaUtil,
nestType: nestService,
injectionType: 'boot-service'
});
}
}
}
});
}
/**
* 5. 自动添加 Logger
*/
addLoggerDependency(javaClass, dependencies) {
// 检查是否有 log.xxx() 或 logger.xxx() 调用
let needsLogger = false;
if (javaClass.methods) {
javaClass.methods.forEach(method => {
if (method.body && (
method.body.includes('log.') ||
method.body.includes('logger.')
)) {
needsLogger = true;
}
});
}
if (needsLogger && !dependencies.has('logger')) {
dependencies.set('logger', {
source: 'auto-logger',
name: 'logger',
javaType: 'Logger',
nestType: 'Logger',
injectionType: 'logger',
isField: true // Logger 作为字段,不在 constructor 中
});
}
}
/**
* 生成 NestJS 构造函数
*/
generateConstructor(dependencies, className) {
// 过滤掉字段依赖(如 Logger
const constructorDeps = dependencies.filter(dep => !dep.isField);
if (constructorDeps.length === 0) {
return ' constructor() {}';
}
const injections = constructorDeps.map(dep => {
return this.generateInjection(dep);
});
return ` constructor(\n${injections.join(',\n')}\n ) {}`;
}
/**
* 生成单个依赖注入
*/
generateInjection(dependency) {
const { injectionType, name, nestType, entityName } = dependency;
switch (injectionType) {
case 'repository':
return ` @InjectRepository(${entityName})\n private readonly ${name}: Repository<${entityName}>`;
case 'service':
return ` private readonly ${name}: ${nestType}`;
case 'boot-service':
return ` private readonly ${name}: ${nestType}`;
default:
return ` private readonly ${name}: ${nestType}`;
}
}
/**
* 生成导入语句
*/
generateImports(dependencies) {
const imports = new Set();
// 基础导入
imports.add("import { Injectable, Logger } from '@nestjs/common';");
// Repository 导入
const hasRepository = dependencies.some(dep => dep.injectionType === 'repository');
if (hasRepository) {
imports.add("import { InjectRepository } from '@nestjs/typeorm';");
imports.add("import { Repository } from 'typeorm';");
}
// Entity 导入
dependencies
.filter(dep => dep.injectionType === 'repository')
.forEach(dep => {
const entityPath = this.generateEntityImportPath(dep.entityName);
imports.add(`import { ${dep.entityName} } from '${entityPath}';`);
});
// Service 导入
dependencies
.filter(dep => dep.injectionType === 'service')
.forEach(dep => {
const servicePath = this.generateServiceImportPath(dep.nestType);
imports.add(`import { ${dep.nestType} } from '${servicePath}';`);
});
// wwjcloud-boot 服务导入
dependencies
.filter(dep => dep.injectionType === 'boot-service')
.forEach(dep => {
const bootPath = this.generateBootServiceImportPath(dep.nestType);
imports.add(`import { ${dep.nestType} } from '${bootPath}';`);
});
return Array.from(imports);
}
/**
* 生成字段声明(如 Logger
*/
generateFields(dependencies, className) {
const fields = [];
const fieldDeps = dependencies.filter(dep => dep.isField);
fieldDeps.forEach(dep => {
if (dep.injectionType === 'logger') {
fields.push(` private readonly logger = new Logger(${className}.name);`);
}
});
return fields;
}
/**
* 辅助方法:映射 Java 类型到 NestJS 类型
*/
mapJavaTypeToNestType(javaType) {
// SysUserMapper -> Repository<SysUser>
if (javaType.endsWith('Mapper')) {
const entityName = javaType.replace('Mapper', '');
return `Repository<${entityName}>`;
}
// SysUserService -> SysUserServiceImplService
if (javaType.endsWith('Service')) {
return this.convertServiceName(javaType);
}
// 工具类
if (this.utilsServiceMapping[javaType]) {
return this.utilsServiceMapping[javaType];
}
return javaType;
}
/**
* 辅助方法:判断注入类型
*/
determineInjectionType(javaType) {
if (javaType.endsWith('Mapper')) return 'repository';
if (javaType.endsWith('Service')) return 'service';
if (this.utilsServiceMapping[javaType]) return 'boot-service';
return 'other';
}
/**
* 辅助方法:转换 Service 名称
*/
convertServiceName(javaServiceName) {
// SysUserService -> SysUserServiceImplService
if (javaServiceName.endsWith('Service')) {
const baseName = javaServiceName.replace('Service', '');
return `${baseName}ServiceImplService`;
}
return javaServiceName;
}
/**
* 辅助方法:生成 Entity 导入路径
*/
generateEntityImportPath(entityName) {
// 简化版本,实际需要根据项目结构调整
const kebabName = this.namingUtils.toKebabCase(entityName);
return `@/entities/${kebabName}.entity`;
}
/**
* 辅助方法:生成 Service 导入路径
*/
generateServiceImportPath(serviceName) {
const kebabName = this.namingUtils.toKebabCase(serviceName);
return `../${kebabName}`;
}
/**
* 辅助方法:生成 wwjcloud-boot 服务导入路径
*/
generateBootServiceImportPath(serviceName) {
const pathMap = {
'RequestContextService': '@/wwjcloud-boot/infra/http/request-context.service',
'CacheService': '@/wwjcloud-boot/infra/cache/cache.service',
'JwtService': '@nestjs/jwt',
'FileUtils': '@/wwjcloud-boot/vendor/utils/file.utils',
'DateUtils': '@/wwjcloud-boot/vendor/utils/date.utils',
'StringUtils': '@/wwjcloud-boot/vendor/utils/string.utils',
'CommonUtils': '@/wwjcloud-boot/vendor/utils/common.utils'
};
return pathMap[serviceName] || '@/wwjcloud-boot';
}
/**
* 主转换方法
*/
convertDependencyInjection(javaClass) {
const dependencies = this.inferDependencies(javaClass);
const className = javaClass.className || 'UnknownClass';
const constructor = this.generateConstructor(dependencies, className);
const imports = this.generateImports(dependencies);
const fields = this.generateFields(dependencies, className);
return {
dependencies,
constructor,
imports,
fields,
stats: {
total: dependencies.length,
explicit: dependencies.filter(d => d.source === 'explicit').length,
inferred: dependencies.filter(d => d.source.startsWith('inferred')).length,
auto: dependencies.filter(d => d.source.startsWith('auto')).length
}
};
}
/**
* 生成完整的服务文件头部
*/
generateServiceHeader(javaClass) {
const result = this.convertDependencyInjection(javaClass);
const className = javaClass.className || 'UnknownClass';
let header = '';
// 导入语句
header += result.imports.join('\n') + '\n\n';
// 类声明和字段
header += `@Injectable()\n`;
header += `export class ${className} {\n`;
// 字段声明(如 Logger
if (result.fields.length > 0) {
header += result.fields.join('\n') + '\n\n';
}
// 构造函数
header += result.constructor + '\n';
return header;
}
}
module.exports = EnhancedDependencyInjectionConverter;

View File

@@ -0,0 +1,365 @@
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const JavaScanner = require('./scanners/java-scanner');
const LayerMapper = require('./mappers/layer-mapper');
const ModuleGenerator = require('./generators/module-generator');
const FrameworkIntegrationValidator = require('./utils/framework-integration-validator');
/**
* Java到NestJS迁移协调器
* 按技术层级组织模块严格遵循NestJS官方规范
*/
class JavaToNestJSMigrationCoordinator {
constructor() {
this.javaPath = '';
this.nestJSPath = '';
this.scanner = new JavaScanner();
this.mapper = new LayerMapper();
this.moduleGenerator = new ModuleGenerator();
this.frameworkValidator = new FrameworkIntegrationValidator();
this.stats = {
startTime: null,
endTime: null,
filesProcessed: 0,
modulesGenerated: 0,
errors: []
};
}
/**
* 执行完整迁移流程
*/
async runMigration() {
console.log('🚀 开始Java到NestJS迁移流程...');
this.stats.startTime = new Date();
try {
// 第1阶段扫描Java项目
console.log('\n📊 第1阶段扫描Java项目结构...');
await this.scanJavaProject();
// 第2阶段映射层级关系
console.log('\n🔄 第2阶段映射层级关系...');
const nestJSModules = this.mapLayers();
// 第3阶段生成NestJS模块
console.log('\n🔧 第3阶段生成NestJS模块...');
await this.generateModules(nestJSModules);
// 第4阶段生成报告
console.log('\n📋 第4阶段生成迁移报告...');
this.generateReport();
this.stats.endTime = new Date();
console.log('\n✅ 迁移流程完成!');
this.printStats();
} catch (error) {
console.error('❌ 迁移过程中发生错误:', error.message);
this.stats.errors.push(error.message);
throw error;
}
}
/**
* 扫描Java项目
*/
async scanJavaProject() {
this.javaPath = '/Users/wanwu/Documents/wanwujie/wwjcloud-nsetjs/niucloud-java/niucloud-core/src/main/java';
this.nestJSPath = path.resolve(__dirname, '../../wwjcloud/libs/wwjcloud-core/src');
console.log(`📁 Java项目路径: ${this.javaPath}`);
console.log(`📁 NestJS项目路径: ${this.nestJSPath}`);
this.scanner.setJavaPath(this.javaPath);
await this.scanner.scanJavaProject();
const scanResults = this.scanner.getScanResults();
this.stats.filesProcessed = Object.values(scanResults).reduce((total, arr) => total + arr.length, 0);
console.log(`📊 扫描完成,共处理 ${this.stats.filesProcessed} 个文件`);
// 验证扫描结果
this.validateScanResults(scanResults);
}
/**
* 验证扫描结果
*/
validateScanResults(scanResults) {
console.log('\n🔍 验证扫描结果...');
// 检查是否有重复文件
const allFiles = Object.values(scanResults).flat();
const uniqueFiles = new Set(allFiles.map(f => f.filePath));
if (allFiles.length !== uniqueFiles.size) {
console.warn(`⚠️ 发现重复文件: ${allFiles.length - uniqueFiles.size}`);
}
// 检查分类准确性
const totalClassified = Object.values(scanResults).reduce((sum, arr) => sum + arr.length, 0);
console.log(`📊 分类文件总数: ${totalClassified}`);
// 检查每个分类的质量
this.validateClassificationQuality(scanResults);
}
/**
* 验证分类质量
*/
validateClassificationQuality(scanResults) {
console.log('\n🔍 验证分类质量...');
// 验证控制器分类
const controllerQuality = this.validateControllerClassification(scanResults.controllers);
console.log(`📋 控制器分类质量: ${controllerQuality.score}/100`);
// 验证服务分类
const serviceQuality = this.validateServiceClassification(scanResults.services);
console.log(`🔧 服务分类质量: ${serviceQuality.score}/100`);
// 验证实体分类
const entityQuality = this.validateEntityClassification(scanResults.entities);
console.log(`🗄️ 实体分类质量: ${entityQuality.score}/100`);
}
/**
* 验证控制器分类质量
*/
validateControllerClassification(controllers) {
let score = 0;
let issues = [];
controllers.forEach(controller => {
const className = controller.className.toLowerCase();
const content = controller.content.toLowerCase();
// 检查类名是否包含controller
if (className.includes('controller')) {
score += 20;
} else {
issues.push(`类名不包含controller: ${controller.className}`);
}
// 检查是否有控制器注解
if (content.includes('@restcontroller') || content.includes('@controller')) {
score += 30;
} else {
issues.push(`缺少控制器注解: ${controller.className}`);
}
// 检查是否有路由映射
if (content.includes('@requestmapping')) {
score += 30;
} else {
issues.push(`缺少路由映射: ${controller.className}`);
}
// 检查是否有HTTP方法映射
if (content.includes('@getmapping') || content.includes('@postmapping')) {
score += 20;
} else {
issues.push(`缺少HTTP方法映射: ${controller.className}`);
}
});
return { score: Math.min(score, 100), issues };
}
/**
* 验证服务分类质量
*/
validateServiceClassification(services) {
let score = 0;
let issues = [];
services.forEach(service => {
const className = service.className.toLowerCase();
const content = service.content.toLowerCase();
// 检查类名是否包含service
if (className.includes('service')) {
score += 30;
} else {
issues.push(`类名不包含service: ${service.className}`);
}
// 检查是否有服务注解
if (content.includes('@service') || content.includes('@component')) {
score += 40;
} else {
issues.push(`缺少服务注解: ${service.className}`);
}
// 检查是否有业务方法
if (content.includes('public') && content.includes('(')) {
score += 30;
} else {
issues.push(`缺少业务方法: ${service.className}`);
}
});
return { score: Math.min(score, 100), issues };
}
/**
* 验证实体分类质量
*/
validateEntityClassification(entities) {
let score = 0;
let issues = [];
entities.forEach(entity => {
const className = entity.className.toLowerCase();
const content = entity.content.toLowerCase();
// 检查类名是否包含entity
if (className.includes('entity') || className.includes('model')) {
score += 25;
} else {
issues.push(`类名不包含entity/model: ${entity.className}`);
}
// 检查是否有实体注解
if (content.includes('@entity') || content.includes('@table')) {
score += 35;
} else {
issues.push(`缺少实体注解: ${entity.className}`);
}
// 检查是否有字段映射
if (content.includes('@column') || content.includes('@id')) {
score += 40;
} else {
issues.push(`缺少字段映射: ${entity.className}`);
}
});
return { score: Math.min(score, 100), issues };
}
/**
* 映射层级关系
*/
mapLayers() {
const scanResults = this.scanner.getScanResults();
const nestJSModules = this.mapper.mapToNestJSModules(scanResults);
console.log('✅ 层级映射完成');
return nestJSModules;
}
/**
* 生成NestJS模块
*/
async generateModules(nestJSModules) {
this.moduleGenerator.setOutputDir(this.nestJSPath);
await this.moduleGenerator.generateAllModules(nestJSModules);
this.stats.modulesGenerated = Object.keys(nestJSModules).length;
console.log(`✅ 生成了 ${this.stats.modulesGenerated} 个模块`);
// 后处理自动生成缺失的Service方法存根
console.log('\n📝 后处理生成缺失的Service方法存根...');
const MethodStubGenerator = require('./generators/method-stub-generator');
const stubGenerator = new MethodStubGenerator();
stubGenerator.process(this.nestJSPath);
// 验证框架集成
console.log('\n🔍 开始验证框架集成...');
const generatedFiles = this.getGeneratedFiles();
const validationResults = this.frameworkValidator.validateFrameworkIntegration(generatedFiles);
this.printFrameworkValidationResults(validationResults);
}
/**
* 生成迁移报告
*/
generateReport() {
const report = {
timestamp: new Date().toISOString(),
stats: this.stats,
modules: [
'CommonModule - 通用功能模块',
'EntityModule - 实体模块',
'ServiceModule - 服务模块',
'ControllerModule - 控制器模块',
'ListenerModule - 监听器模块',
'JobModule - 任务模块'
]
};
const reportPath = path.join(__dirname, 'migration-report.json');
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));
console.log(`📋 迁移报告已生成: ${reportPath}`);
}
/**
* 获取生成的文件列表
*/
getGeneratedFiles() {
const files = [];
const nestJSDir = this.nestJSPath;
if (fs.existsSync(nestJSDir)) {
const walkDir = (dir) => {
const items = fs.readdirSync(dir);
items.forEach(item => {
const itemPath = path.join(dir, item);
const stat = fs.statSync(itemPath);
if (stat.isDirectory()) {
walkDir(itemPath);
} else if (item.endsWith('.ts')) {
files.push({ path: itemPath, name: item });
}
});
};
walkDir(nestJSDir);
}
return files;
}
/**
* 打印框架验证结果
*/
printFrameworkValidationResults(validationResults) {
if (!validationResults || !validationResults.summary) {
console.log('⚠️ 框架验证结果为空');
return;
}
console.log('\n🔍 框架集成验证结果:');
console.log(`📊 总文件数: ${validationResults.summary.totalFiles || 0}`);
console.log(`✅ 框架导入: ${validationResults.summary.frameworkImports?.['✅'] || 0}/${(validationResults.summary.frameworkImports?.['✅'] || 0) + (validationResults.summary.frameworkImports?.['❌'] || 0)}`);
console.log(`✅ 框架服务: ${validationResults.summary.frameworkServices?.['✅'] || 0}/${(validationResults.summary.frameworkServices?.['✅'] || 0) + (validationResults.summary.frameworkServices?.['❌'] || 0)}`);
console.log(`✅ 框架配置: ${validationResults.summary.frameworkConfig?.['✅'] || 0}/${(validationResults.summary.frameworkConfig?.['✅'] || 0) + (validationResults.summary.frameworkConfig?.['❌'] || 0)}`);
console.log(`✅ 框架事件: ${validationResults.summary.frameworkEvents?.['✅'] || 0}/${(validationResults.summary.frameworkEvents?.['✅'] || 0) + (validationResults.summary.frameworkEvents?.['❌'] || 0)}`);
console.log(`✅ 框架队列: ${validationResults.summary.frameworkQueues?.['✅'] || 0}/${(validationResults.summary.frameworkQueues?.['✅'] || 0) + (validationResults.summary.frameworkQueues?.['❌'] || 0)}`);
console.log(`✅ 数据库兼容: ${validationResults.summary.databaseCompatibility?.['✅'] || 0}/${(validationResults.summary.databaseCompatibility?.['✅'] || 0) + (validationResults.summary.databaseCompatibility?.['❌'] || 0)}`);
console.log(`✅ API兼容: ${validationResults.summary.apiCompatibility?.['✅'] || 0}/${(validationResults.summary.apiCompatibility?.['✅'] || 0) + (validationResults.summary.apiCompatibility?.['❌'] || 0)}`);
}
/**
* 打印统计信息
*/
printStats() {
const duration = this.stats.endTime - this.stats.startTime;
console.log('\n📊 迁移统计:');
console.log(`⏱️ 总耗时: ${duration}ms`);
console.log(`📁 处理文件: ${this.stats.filesProcessed}`);
console.log(`🔧 生成模块: ${this.stats.modulesGenerated}`);
console.log(`❌ 错误数量: ${this.stats.errors.length}`);
}
}
// 如果直接运行此文件,则执行迁移
if (require.main === module) {
const coordinator = new JavaToNestJSMigrationCoordinator();
coordinator.runMigration().catch(console.error);
}
module.exports = JavaToNestJSMigrationCoordinator;