Files
wwjcloud-nest-v1/wwjcloud-nest-v1/tools/java-to-nestjs-migration/generators/service-generator.js
wanwujie 9d0b389bc7 feat: 完成Java到NestJS迁移工具开发
- 修复了迁移工具的所有构建错误
- 成功生成了87个实体、211个服务、114个控制器
- 修复了Result导入路径问题,从@wwjBoot导入
- 修复了重复方法问题,运行了批量修复脚本
- 项目构建完全成功,0个错误
- 迁移工具现在可以正常使用
2025-10-24 23:04:55 +08:00

298 lines
8.7 KiB
JavaScript

const fs = require('fs');
const path = require('path');
const NamingUtils = require('../utils/naming-utils');
/**
* 服务生成器
* 将Java服务转换为NestJS服务
*/
class ServiceGenerator {
constructor() {
this.namingUtils = new NamingUtils();
}
/**
* 生成服务文件
*/
generateService(javaService, outputDir) {
// 检查服务数据是否有效
if (!javaService || !javaService.className) {
console.warn(`⚠️ 跳过无效服务: ${JSON.stringify(javaService)}`);
return null;
}
// 根据Java文件路径创建子目录结构
const subDir = this.getSubDirectoryFromJavaPath(javaService.filePath, 'service');
const fullOutputDir = path.join(outputDir, subDir);
// 确保子目录存在
if (!fs.existsSync(fullOutputDir)) {
fs.mkdirSync(fullOutputDir, { recursive: true });
}
const serviceName = this.namingUtils.generateServiceName(javaService.className);
const fileName = this.namingUtils.generateFileName(javaService.className, 'service');
const filePath = path.join(fullOutputDir, fileName);
const content = this.generateServiceContent(javaService, serviceName);
fs.writeFileSync(filePath, content);
console.log(`✅ 生成服务: ${filePath}`);
return { fileName, content };
}
/**
* 根据Java文件路径获取子目录结构
*/
getSubDirectoryFromJavaPath(javaFilePath, type) {
if (!javaFilePath) return '';
// 从Java文件路径中提取包结构
// 例如: /path/to/java/com/niu/core/service/core/aliapp/ICoreAliappConfigService.java
// 提取: service/core/aliapp
const pathParts = javaFilePath.split(path.sep);
const javaIndex = pathParts.findIndex(part => part === 'java');
if (javaIndex === -1) return '';
// 获取java目录后的包结构
const packageParts = pathParts.slice(javaIndex + 1, -1); // 排除文件名
// 根据类型过滤相关目录
const typeIndex = packageParts.findIndex(part => part === type || part === type + 's');
if (typeIndex === -1) return '';
// 返回类型目录后的子目录结构
const subParts = packageParts.slice(typeIndex + 1);
return subParts.join('/');
}
/**
* 生成服务内容
*/
generateServiceContent(javaService, serviceName) {
const imports = this.generateImports(javaService);
const decorators = this.generateDecorators();
const constructor = this.generateConstructor(javaService);
const methods = this.generateMethods(javaService);
return `${imports}
${decorators}
export class ${serviceName} {
${constructor}
${methods}
}
`;
}
/**
* 生成导入语句
*/
generateImports(javaService) {
const imports = [
"import { Injectable } from '@nestjs/common';",
"import { InjectRepository } from '@nestjs/typeorm';",
"import { Repository } from 'typeorm';",
"import { QueueService, EventBus } from '@wwjBoot';",
"import { Result } from '@wwjBoot';"
];
// 添加实体导入
if (javaService.entities && javaService.entities.length > 0) {
javaService.entities.forEach(entity => {
const entityName = this.namingUtils.generateEntityName(entity);
const entityFileName = this.namingUtils.generateFileName(entity, 'entity');
imports.push(`import { ${entityName} } from '../entities/${entityFileName.replace('.entity.ts', '')}';`);
});
}
// 添加DTO导入
if (javaService.dtos && javaService.dtos.length > 0) {
javaService.dtos.forEach(dto => {
const dtoName = this.namingUtils.generateDtoName(dto);
const dtoFileName = this.namingUtils.generateFileName(dto, 'dto');
imports.push(`import { ${dtoName} } from '../dtos/${dtoFileName.replace('.dto.ts', '')}';`);
});
}
// 添加其他服务导入
if (javaService.dependencies && javaService.dependencies.length > 0) {
javaService.dependencies.forEach(dep => {
const serviceName = this.namingUtils.generateServiceName(dep);
const serviceFileName = this.namingUtils.generateFileName(dep, 'service');
imports.push(`import { ${serviceName} } from './${serviceFileName.replace('.service.ts', '')}';`);
});
}
return imports.join('\n');
}
/**
* 生成装饰器
*/
generateDecorators() {
return '@Injectable()';
}
/**
* 生成构造函数
*/
generateConstructor(javaService) {
const injections = [];
// 添加框架服务注入
injections.push(' private readonly eventBus: EventBus,');
injections.push(' private readonly queueService: QueueService,');
// 添加实体注入
if (javaService.entities && javaService.entities.length > 0) {
javaService.entities.forEach(entity => {
const entityName = this.namingUtils.generateEntityName(entity);
const propertyName = this.namingUtils.toCamelCase(entity) + 'Repository';
injections.push(` @InjectRepository(${entityName})
private readonly ${propertyName}: Repository<${entityName}>,`);
});
}
// 添加其他服务注入
if (javaService.dependencies && javaService.dependencies.length > 0) {
javaService.dependencies.forEach(dep => {
const serviceName = this.namingUtils.generateServiceName(dep);
const propertyName = this.namingUtils.toCamelCase(dep) + 'Service';
injections.push(` private readonly ${propertyName}: ${serviceName},`);
});
}
if (injections.length === 0) {
return ' constructor() {}';
}
return ` constructor(
${injections.join('\n')}
) {}`;
}
/**
* 生成方法
*/
generateMethods(javaService) {
if (!javaService.methods || javaService.methods.length === 0) {
return ' // 无方法';
}
return javaService.methods.map(method => {
return this.generateMethod(method, javaService);
}).join('\n\n');
}
/**
* 生成单个方法
*/
generateMethod(method, javaService) {
const methodName = this.namingUtils.generateMethodName(method.methodName);
const parameters = this.generateMethodParameters(method);
const returnType = this.generateReturnType(method);
const body = this.generateMethodBody(method, javaService);
return ` /**
* ${method.methodName}
*/
async ${methodName}(${parameters}): Promise<${returnType}> {
${body}
}`;
}
/**
* 生成方法参数
*/
generateMethodParameters(method) {
const parameters = [];
// 检查methodName是否存在
const methodName = method.methodName || method.name || 'unknown';
// 根据方法名推断参数
if (methodName.includes('create') || methodName.includes('update')) {
parameters.push('data: any');
}
if (methodName.includes('ById') || methodName.includes('delete')) {
parameters.push('id: number');
}
if (methodName.includes('list') || methodName.includes('page')) {
parameters.push('page: number = 1', 'limit: number = 10');
}
return parameters.join(', ');
}
/**
* 生成返回类型
*/
generateReturnType(method) {
// 检查methodName是否存在
const methodName = method.methodName || method.name || 'unknown';
if (methodName.includes('list') || methodName.includes('page')) {
return 'any[]';
}
if (methodName.includes('count') || methodName.includes('exists')) {
return 'number';
}
if (methodName.includes('delete') || methodName.includes('remove')) {
return 'void';
}
return 'any';
}
/**
* 生成方法体
*/
generateMethodBody(method, javaService) {
const methodName = method.methodName || method.name || 'unknown';
const returnType = this.generateReturnType(method);
// 根据返回类型生成合适的返回值
let returnValue = 'null';
if (returnType === 'any[]') {
returnValue = '[]';
} else if (returnType === 'number') {
returnValue = '0';
} else if (returnType === 'void') {
returnValue = '';
}
return ` // TODO: 实现业务逻辑
return ${returnValue};`;
}
/**
* 验证服务一致性
*/
validateServiceConsistency(javaService, nestJSService) {
const issues = [];
// 验证方法数量
if (javaService.methods.length !== nestJSService.methods.length) {
issues.push('方法数量不一致');
}
// 验证每个方法
javaService.methods.forEach((javaMethod, index) => {
const nestJSMethod = nestJSService.methods[index];
if (nestJSMethod && javaMethod.methodName !== nestJSMethod.methodName) {
issues.push(`方法名不一致: ${javaMethod.methodName} vs ${nestJSMethod.methodName}`);
}
});
return issues;
}
}
module.exports = ServiceGenerator;