🐛 问题根源: - 转换器已正确使用框架能力(JsonUtils/CommonUtils/StringUtils) - 但service-generator未调用转换器的analyzeImports() - 导致工具类import缺失 ✅ 修复内容: 1. service-generator.analyzeAdditionalImports() - 调用methodConverter.analyzeImports()获取完整import列表 - 新增Boot层工具类检测: JsonUtils/CommonUtils/StringUtils - 新增服务检测: AppConfigService/RequestContextService 2. service-generator.generateImports() - 动态添加Boot层工具类到import语句 3. service-generator.generateConstructor() - 自动注入AppConfigService (this.appConfig) - 自动注入RequestContextService (this.requestContext) 🎯 预期效果: - 15,474个错误 → 预计降到5000以内 - 'Cannot find name JsonUtils' → 0 - 'Cannot find name CommonUtils' → 0 - 'Cannot find name StringUtils' → 0
659 lines
22 KiB
JavaScript
659 lines
22 KiB
JavaScript
const fs = require('fs');
|
||
const path = require('path');
|
||
const NamingUtils = require('../utils/naming-utils');
|
||
const ServiceMethodConverter = require('../converters/service-method-converter');
|
||
|
||
/**
|
||
* 服务生成器
|
||
* 将Java服务转换为NestJS服务
|
||
*/
|
||
class ServiceGenerator {
|
||
constructor(outputDir = null) {
|
||
this.namingUtils = new NamingUtils();
|
||
this.methodConverter = new ServiceMethodConverter();
|
||
this.outputDir = outputDir;
|
||
}
|
||
|
||
/**
|
||
* 检查Entity文件是否存在
|
||
*/
|
||
entityFileExists(entityName) {
|
||
if (!this.outputDir) return false;
|
||
|
||
const entityFileName = this.namingUtils.generateFileName(entityName, 'entity');
|
||
const entityPath = path.join(this.outputDir, 'entities', entityFileName);
|
||
return fs.existsSync(entityPath);
|
||
}
|
||
|
||
/**
|
||
* 生成服务文件
|
||
*/
|
||
generateService(javaService, outputDir) {
|
||
this.outputDir = outputDir; // 更新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);
|
||
|
||
// ✅ 修复:检查Service是否已实现,不覆盖已实现的Service
|
||
if (fs.existsSync(filePath)) {
|
||
const existingContent = fs.readFileSync(filePath, 'utf-8');
|
||
|
||
// 检查是否已实现(不只是TODO占位符)
|
||
const isImplemented = this.isServiceImplemented(existingContent);
|
||
|
||
if (isImplemented) {
|
||
console.log(`⏭️ 跳过已实现服务: ${filePath}`);
|
||
return { fileName, content: existingContent, skipped: true };
|
||
}
|
||
|
||
console.log(`🔄 覆盖TODO占位服务: ${filePath}`);
|
||
}
|
||
|
||
const content = this.generateServiceContent(javaService, serviceName);
|
||
fs.writeFileSync(filePath, content);
|
||
|
||
console.log(`✅ 生成服务: ${filePath}`);
|
||
return { fileName, content };
|
||
}
|
||
|
||
/**
|
||
* 检查Service是否已实现(不只是TODO占位符)
|
||
*/
|
||
isServiceImplemented(content) {
|
||
// 检查是否包含实际业务逻辑的标志:
|
||
// 1. 有TypeORM的@InjectRepository
|
||
// 2. 有JwtService
|
||
// 3. 有bcrypt
|
||
// 4. 方法体中不只是return null/undefined
|
||
// 5. 有实际的业务代码(非TODO注释)
|
||
|
||
const implementationMarkers = [
|
||
/@InjectRepository/,
|
||
/JwtService/,
|
||
/bcrypt/,
|
||
/await.*Repository/,
|
||
/this\..*Repository\./,
|
||
/async\s+\w+\([^)]*\)\s*:\s*Promise<[^>]+>\s*{\s*[^}]*(?!\/\/\s*TODO)(?!return\s+null)/,
|
||
];
|
||
|
||
// 如果包含任一实现标志,认为是已实现
|
||
return implementationMarkers.some(marker => marker.test(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('/');
|
||
}
|
||
|
||
/**
|
||
* 计算从Service到entities目录的相对路径
|
||
*/
|
||
calculateEntityPath(javaFilePath) {
|
||
if (!javaFilePath) return '../../entities';
|
||
|
||
// 获取Service的子目录深度
|
||
const subDir = this.getSubDirectoryFromJavaPath(javaFilePath, 'service');
|
||
|
||
// 计算需要返回的层级数
|
||
// services目录本身算1层,子目录每层+1
|
||
const depth = subDir ? subDir.split('/').length + 1 : 1;
|
||
const upLevels = '../'.repeat(depth + 1); // +1是因为要从services目录出去到src
|
||
|
||
return `${upLevels}entities`;
|
||
}
|
||
|
||
/**
|
||
* 生成服务内容
|
||
*
|
||
* ✅ 增强:自动分析方法体,添加需要的imports
|
||
*/
|
||
generateServiceContent(javaService, serviceName) {
|
||
// 先生成方法,以便分析需要哪些imports
|
||
const methods = this.generateMethods(javaService);
|
||
|
||
// 分析方法体,获取需要的imports
|
||
const additionalImports = this.analyzeAdditionalImports(methods);
|
||
|
||
const imports = this.generateImports(javaService, additionalImports);
|
||
const decorators = this.generateDecorators();
|
||
const constructor = this.generateConstructor(javaService, additionalImports);
|
||
|
||
return `${imports}
|
||
|
||
${decorators}
|
||
export class ${serviceName} {
|
||
${constructor}
|
||
${methods}
|
||
}
|
||
`;
|
||
}
|
||
|
||
/**
|
||
* 分析方法体,识别需要的额外imports
|
||
*
|
||
* ✅ 调用 ServiceMethodConverter.analyzeImports 获取完整的import列表
|
||
*/
|
||
analyzeAdditionalImports(methodsCode) {
|
||
const imports = {
|
||
nestjs: new Set(),
|
||
nodeModules: new Set(),
|
||
boot: new Set()
|
||
};
|
||
|
||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
// 【调用转换器的analyzeImports,获取V1框架能力的imports】
|
||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
const converterImports = this.methodConverter.analyzeImports(methodsCode);
|
||
|
||
converterImports.forEach(importItem => {
|
||
if (importItem === 'JsonUtils' || importItem === 'CommonUtils' || importItem === 'StringUtils') {
|
||
imports.boot.add(importItem);
|
||
} else if (importItem === 'AppConfigService') {
|
||
imports.boot.add('AppConfigService');
|
||
} else if (importItem === 'nestjs:BadRequestException') {
|
||
imports.nestjs.add('BadRequestException');
|
||
} else if (importItem === 'nestjs:UnauthorizedException') {
|
||
imports.nestjs.add('UnauthorizedException');
|
||
} else if (importItem === 'node:fs') {
|
||
imports.nodeModules.add('fs');
|
||
} else if (importItem === 'node:path') {
|
||
imports.nodeModules.add('path');
|
||
} else if (importItem === 'boot:RequestContextService') {
|
||
imports.boot.add('RequestContextService');
|
||
}
|
||
});
|
||
|
||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
// 【兼容旧的检测逻辑(备用)】
|
||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
||
// NestJS异常
|
||
if (methodsCode.includes('BadRequestException')) {
|
||
imports.nestjs.add('BadRequestException');
|
||
}
|
||
if (methodsCode.includes('UnauthorizedException')) {
|
||
imports.nestjs.add('UnauthorizedException');
|
||
}
|
||
|
||
// Node.js模块
|
||
if (methodsCode.includes('fs.')) {
|
||
imports.nodeModules.add('fs');
|
||
}
|
||
if (methodsCode.includes('path.')) {
|
||
imports.nodeModules.add('path');
|
||
}
|
||
|
||
// Boot层工具类
|
||
if (methodsCode.includes('JsonUtils.')) {
|
||
imports.boot.add('JsonUtils');
|
||
}
|
||
if (methodsCode.includes('CommonUtils.')) {
|
||
imports.boot.add('CommonUtils');
|
||
}
|
||
if (methodsCode.includes('StringUtils.')) {
|
||
imports.boot.add('StringUtils');
|
||
}
|
||
if (methodsCode.includes('this.appConfig.')) {
|
||
imports.boot.add('AppConfigService');
|
||
}
|
||
if (methodsCode.includes('this.requestContext.')) {
|
||
imports.boot.add('RequestContextService');
|
||
}
|
||
|
||
return {
|
||
nestjs: Array.from(imports.nestjs),
|
||
nodeModules: Array.from(imports.nodeModules),
|
||
boot: Array.from(imports.boot)
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 生成导入语句
|
||
*
|
||
* ✅ 增强:接收额外的imports(NestJS异常、Node.js模块、Boot服务)
|
||
*/
|
||
generateImports(javaService, additionalImports = {}) {
|
||
const imports = [
|
||
"import { Injectable } from '@nestjs/common';"
|
||
];
|
||
|
||
// ✅ NestJS异常(按需导入)
|
||
const nestjsImports = ['Injectable'];
|
||
if (additionalImports.nestjs && additionalImports.nestjs.length > 0) {
|
||
additionalImports.nestjs.forEach(item => {
|
||
if (!nestjsImports.includes(item)) {
|
||
nestjsImports.push(item);
|
||
}
|
||
});
|
||
}
|
||
if (nestjsImports.length > 1) {
|
||
imports[0] = `import { ${nestjsImports.join(', ')} } from '@nestjs/common';`;
|
||
}
|
||
|
||
// TypeORM
|
||
imports.push("import { InjectRepository } from '@nestjs/typeorm';");
|
||
imports.push("import { Repository } from 'typeorm';");
|
||
|
||
// ✅ Boot层(按需导入)
|
||
// 基础服务(总是导入)
|
||
const bootImports = ['QueueService', 'EventBus', 'Result'];
|
||
|
||
// 添加额外的Boot层imports(工具类、服务等)
|
||
if (additionalImports.boot && additionalImports.boot.length > 0) {
|
||
additionalImports.boot.forEach(item => {
|
||
if (!bootImports.includes(item)) {
|
||
bootImports.push(item);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 生成import语句
|
||
if (bootImports.length > 0) {
|
||
imports.push(`import { ${bootImports.join(', ')} } from '@wwjBoot';`);
|
||
}
|
||
|
||
// ✅ Node.js模块(按需导入)
|
||
if (additionalImports.nodeModules && additionalImports.nodeModules.length > 0) {
|
||
additionalImports.nodeModules.forEach(module => {
|
||
if (module === 'fs') {
|
||
imports.push(`import * as fs from 'fs';`);
|
||
} else if (module === 'path') {
|
||
imports.push(`import * as path from 'path';`);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 计算到entities目录的相对路径
|
||
const entityRelativePath = this.calculateEntityPath(javaService.filePath);
|
||
|
||
// 推断主实体并添加导入(仅当Entity文件存在时)
|
||
const entityName = this.inferEntityName(javaService.className);
|
||
if (this.entityFileExists(entityName)) {
|
||
const pascalEntityName = this.namingUtils.toPascalCase(entityName);
|
||
const entityFileName = this.namingUtils.generateFileName(entityName, 'entity');
|
||
imports.push(`import { ${pascalEntityName} } from '${entityRelativePath}/${entityFileName.replace('.ts', '')}';`);
|
||
} else {
|
||
console.warn(`⚠️ Entity文件不存在,跳过导入: ${entityName} (Service: ${javaService.className})`);
|
||
}
|
||
|
||
// 添加额外实体导入(仅当Entity文件存在时)
|
||
if (javaService.entities && javaService.entities.length > 0) {
|
||
javaService.entities.forEach(entity => {
|
||
// 跳过已经导入的主实体
|
||
if (entity.toLowerCase() === entityName.toLowerCase()) {
|
||
return;
|
||
}
|
||
if (this.entityFileExists(entity)) {
|
||
const extraEntityName = this.namingUtils.generateEntityName(entity);
|
||
const extraEntityFileName = this.namingUtils.generateFileName(entity, 'entity');
|
||
imports.push(`import { ${extraEntityName} } from '${entityRelativePath}/${extraEntityFileName.replace('.ts', '')}';`);
|
||
} else {
|
||
console.warn(`⚠️ 额外Entity文件不存在,跳过导入: ${entity} (Service: ${javaService.className})`);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 添加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('.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()';
|
||
}
|
||
|
||
/**
|
||
* 生成构造函数
|
||
*
|
||
* ✅ 增强:根据additionalImports注入ConfigService
|
||
*/
|
||
generateConstructor(javaService, additionalImports = {}) {
|
||
const injections = [];
|
||
|
||
// ✅ 添加Boot层服务注入(按需)
|
||
if (additionalImports.boot && additionalImports.boot.includes('AppConfigService')) {
|
||
injections.push(' private readonly appConfig: AppConfigService,');
|
||
}
|
||
if (additionalImports.boot && additionalImports.boot.includes('RequestContextService')) {
|
||
injections.push(' private readonly requestContext: RequestContextService,');
|
||
}
|
||
if (additionalImports.boot && additionalImports.boot.includes('ConfigService')) {
|
||
injections.push(' private readonly config: ConfigService,');
|
||
}
|
||
|
||
// 添加框架服务注入(总是注入)
|
||
injections.push(' private readonly eventBus: EventBus,');
|
||
injections.push(' private readonly queueService: QueueService,');
|
||
|
||
// 推断主实体并注入 Repository(仅当Entity文件存在时)
|
||
const entityName = this.inferEntityName(javaService.className);
|
||
if (this.entityFileExists(entityName)) {
|
||
const pascalEntityName = this.namingUtils.toPascalCase(entityName);
|
||
const repositoryPropertyName = this.namingUtils.toCamelCase(entityName) + 'Repository';
|
||
injections.push(` @InjectRepository(${pascalEntityName})
|
||
private readonly ${repositoryPropertyName}: Repository<${pascalEntityName}>,`);
|
||
}
|
||
|
||
// 添加额外实体注入(如果有,且Entity文件存在)
|
||
if (javaService.entities && javaService.entities.length > 0) {
|
||
javaService.entities.forEach(entity => {
|
||
// 跳过已经注入的主实体
|
||
if (entity.toLowerCase() === entityName.toLowerCase()) {
|
||
return;
|
||
}
|
||
if (this.entityFileExists(entity)) {
|
||
const extraEntityName = this.namingUtils.generateEntityName(entity);
|
||
const propertyName = this.namingUtils.toCamelCase(entity) + 'Repository';
|
||
injections.push(` @InjectRepository(${extraEntityName})
|
||
private readonly ${propertyName}: Repository<${extraEntityName}>,`);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 添加其他服务注入
|
||
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 ' // 无方法';
|
||
}
|
||
|
||
// 过滤并去重:只生成public方法,使用Set记录已生成的方法名
|
||
const generatedMethodNames = new Set();
|
||
const uniqueMethods = [];
|
||
|
||
for (const method of javaService.methods) {
|
||
// 只处理public方法(排除构造函数)
|
||
if (method.accessModifier === 'public' && method.methodName !== javaService.className) {
|
||
const methodName = this.namingUtils.generateMethodName(method.methodName);
|
||
if (!generatedMethodNames.has(methodName)) {
|
||
generatedMethodNames.add(methodName);
|
||
uniqueMethods.push(method);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (uniqueMethods.length === 0) {
|
||
return ' // 无public方法';
|
||
}
|
||
|
||
return uniqueMethods.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) {
|
||
// 简化:所有方法都接受任意参数,避免参数类型不匹配
|
||
return '...args: any[]';
|
||
}
|
||
|
||
/**
|
||
* 生成返回类型
|
||
*/
|
||
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';
|
||
}
|
||
|
||
/**
|
||
* 生成方法体
|
||
*
|
||
* ✅ 新逻辑:使用ServiceMethodConverter转换Java方法体
|
||
*/
|
||
generateMethodBody(method, javaService) {
|
||
// 如果Java方法有方法体,使用转换器转换
|
||
if (method.methodBody && method.methodBody.trim() !== '') {
|
||
// 准备上下文信息
|
||
const context = {
|
||
dependencies: javaService.dependencies || [],
|
||
className: javaService.className
|
||
};
|
||
|
||
// 使用转换器转换Java方法体
|
||
return this.methodConverter.convertMethodBody(method.methodBody, context);
|
||
}
|
||
|
||
// 如果没有Java方法体,返回TODO占位符(按返回类型)
|
||
const returnType = this.generateReturnType(method);
|
||
|
||
if (returnType === 'any[]') {
|
||
return ` // TODO: 实现业务逻辑\n return [];`;
|
||
} else if (returnType === 'number') {
|
||
return ` // TODO: 实现业务逻辑\n return 0;`;
|
||
} else if (returnType === 'void') {
|
||
return ` // TODO: 实现业务逻辑\n return;`;
|
||
} else if (returnType.includes('PageResult') || returnType.includes('{ items')) {
|
||
return ` // TODO: 实现业务逻辑\n return { items: [], total: 0 };`;
|
||
} else {
|
||
return ` // TODO: 实现业务逻辑\n return null;`;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 推断实体名称
|
||
*/
|
||
inferEntityName(serviceClassName) {
|
||
// 从 SiteServiceImpl -> Site
|
||
return serviceClassName
|
||
.replace(/ServiceImpl$/, '')
|
||
.replace(/Service$/, '')
|
||
.replace(/^I/, ''); // 移除接口前缀 I
|
||
}
|
||
|
||
/**
|
||
* 生成列表查询方法体
|
||
*/
|
||
generateListMethodBody(repositoryName) {
|
||
return ` const skip = (page - 1) * limit;
|
||
const [items, total] = await this.${repositoryName}.findAndCount({
|
||
skip,
|
||
take: limit,
|
||
order: { createTime: 'DESC' },
|
||
});
|
||
return { items, total };`;
|
||
}
|
||
|
||
/**
|
||
* 生成详情查询方法体
|
||
*/
|
||
generateGetByIdMethodBody(repositoryName) {
|
||
return ` const entity = await this.${repositoryName}.findOne({ where: { id } });
|
||
if (!entity) {
|
||
throw new Error('记录不存在');
|
||
}
|
||
return entity;`;
|
||
}
|
||
|
||
/**
|
||
* 生成创建方法体
|
||
*/
|
||
generateCreateMethodBody(repositoryName) {
|
||
return ` const entity = this.${repositoryName}.create(data);
|
||
const saved = await this.${repositoryName}.save(entity);
|
||
|
||
// 发布创建事件
|
||
await this.eventBus.publish('entity.created', { entity: saved });
|
||
|
||
return saved;`;
|
||
}
|
||
|
||
/**
|
||
* 生成更新方法体
|
||
*/
|
||
generateUpdateMethodBody(repositoryName) {
|
||
return ` const entity = await this.${repositoryName}.findOne({ where: { id } });
|
||
if (!entity) {
|
||
throw new Error('记录不存在');
|
||
}
|
||
|
||
Object.assign(entity, data);
|
||
const updated = await this.${repositoryName}.save(entity);
|
||
|
||
// 发布更新事件
|
||
await this.eventBus.publish('entity.updated', { entity: updated });
|
||
|
||
return updated;`;
|
||
}
|
||
|
||
/**
|
||
* 生成删除方法体
|
||
*/
|
||
generateDeleteMethodBody(repositoryName) {
|
||
return ` const entity = await this.${repositoryName}.findOne({ where: { id } });
|
||
if (!entity) {
|
||
throw new Error('记录不存在');
|
||
}
|
||
|
||
await this.${repositoryName}.remove(entity);
|
||
|
||
// 发布删除事件
|
||
await this.eventBus.publish('entity.deleted', { entity });`;
|
||
}
|
||
|
||
/**
|
||
* 生成计数方法体
|
||
*/
|
||
generateCountMethodBody(repositoryName) {
|
||
return ` return await this.${repositoryName}.count();`;
|
||
}
|
||
|
||
/**
|
||
* 生成存在性检查方法体
|
||
*/
|
||
generateExistsMethodBody(repositoryName) {
|
||
return ` const count = await this.${repositoryName}.count({ where: { id } });
|
||
return count > 0;`;
|
||
}
|
||
|
||
/**
|
||
* 验证服务一致性
|
||
*/
|
||
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;
|