#!/usr/bin/env node const fs = require('fs'); const path = require('path'); const ServiceGenerator = require('./generators/service-generator'); const EntityGenerator = require('./generators/entity-generator'); const ModuleGenerator = require('./generators/module-generator'); const ControllerGenerator = require('./generators/controller-generator'); const ValidatorGenerator = require('./generators/validator-generator'); // const MiddlewareGenerator = require('./generators/middleware-generator'); // 已废弃,使用Core层Guards+Interceptors+Pipes const RouteGenerator = require('./generators/route-generator'); const JobGenerator = require('./generators/job-generator'); const ListenerGenerator = require('./generators/listener-generator'); // const CommandGenerator = require('./generators/command-generator'); // 文件不存在,暂时注释 const DictGenerator = require('./generators/dict-generator'); const QualityGate = require('./generators/quality-gate'); const IncrementalUpdater = require('./incremental-updater'); /** * 🎯 迁移协调器 * 协调所有工具的执行,按步骤完成PHP到NestJS的迁移 */ class MigrationCoordinator { constructor() { this.config = { phpBasePath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/niucloud-php/niucloud', nestjsBasePath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest/src/core', discoveryResultPath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/tools/php-discovery-result.json', enableJobs: true, enableListeners: true, enableCommands: false, dryRun: false, incrementalMode: process.env.INCREMENTAL === 'true' || process.argv.includes('--incremental') }; this.stats = { totalSteps: 0, completedSteps: 0, failedSteps: 0, startTime: null, endTime: null, errors: 0 }; } /** * 🚀 启动完整自动化迁移工具 */ async run() { console.log('🚀 启动完整自动化迁移工具...'); if (this.config.incrementalMode) { console.log('🔄 增量模式:仅处理变更的文件'); return await this.runIncrementalUpdate(); } else { console.log('🏗️ 完整模式:重新生成所有文件'); return await this.runFullMigration(); } } /** * 🔄 运行增量更新 */ async runIncrementalUpdate() { console.log('🔄 启动增量更新模式...\n'); try { const incrementalUpdater = new IncrementalUpdater(); await incrementalUpdater.run(); console.log('✅ 增量更新完成'); return true; } catch (error) { console.error('❌ 增量更新失败:', error.message); return false; } } /** * 🏗️ 运行完整迁移 */ async runFullMigration() { console.log('目标:完整迁移PHP项目到NestJS,包括所有组件\n'); this.stats.startTime = new Date(); try { // 第1阶段:加载PHP文件发现结果 console.log('📊 第1阶段:加载PHP文件发现结果...'); await this.loadDiscoveryData(); console.log('✅ 第1阶段完成 - 数据加载成功'); // 第2阶段:创建完整模块结构 console.log('📊 第2阶段:创建完整模块结构...'); await this.createCompleteModuleStructure(); console.log('✅ 第2阶段完成 - 模块结构创建成功'); // 第3阶段:生成实体(数据模型层) console.log('📊 第3阶段:生成实体...'); await this.generateEntities(); console.log('🔍 验证实体生成结果...'); await this.validateEntities(); console.log('✅ 第3阶段完成 - 实体生成和验证成功'); // 第4阶段:生成服务(业务逻辑层) console.log('📊 第4阶段:生成服务...'); await this.generateServices(); console.log('🔍 验证服务生成结果...'); await this.validateServices(); console.log('✅ 第4阶段完成 - 服务生成和验证成功'); // 第5阶段:生成验证器(依赖服务) console.log('📊 第5阶段:生成验证器...'); await this.generateValidators(); console.log('🔍 验证验证器生成结果...'); await this.validateValidators(); console.log('✅ 第5阶段完成 - 验证器生成和验证成功'); // 第6阶段:生成控制器(依赖服务和验证器) console.log('📊 第6阶段:生成控制器...'); await this.generateControllersWithClassification(); console.log('🔍 验证控制器生成结果...'); await this.validateControllers(); console.log('✅ 第6阶段完成 - 控制器生成和验证成功'); // 第7阶段:生成路由(依赖控制器) console.log('📊 第7阶段:生成路由...'); await this.generateRoutes(); console.log('🔍 验证路由生成结果...'); await this.validateRoutes(); console.log('✅ 第7阶段完成 - 路由生成和验证成功'); // 第8阶段:生成任务 if (this.config.enableJobs) { console.log('📊 第8阶段:生成任务...'); await this.generateJobs(); console.log('🔍 验证任务生成结果...'); await this.validateJobs(); console.log('✅ 第8阶段完成 - 任务生成和验证成功'); } else { console.log('⏭️ 跳过任务生成 (已禁用)'); } // 第9阶段:生成监听器 if (this.config.enableListeners) { console.log('📊 第9阶段:生成监听器...'); await this.generateListeners(); console.log('🔍 验证监听器生成结果...'); await this.validateListeners(); console.log('✅ 第9阶段完成 - 监听器生成和验证成功'); } else { console.log('⏭️ 跳过监听器生成 (已禁用)'); } // 第10阶段:生成命令 if (this.config.enableCommands) { console.log('📊 第10阶段:生成命令...'); await this.generateCommands(); console.log('🔍 验证命令生成结果...'); await this.validateCommands(); console.log('✅ 第10阶段完成 - 命令生成和验证成功'); } else { console.log('⏭️ 跳过命令生成 (已禁用)'); } // 第11阶段:生成字典 console.log('📊 第11阶段:生成字典...'); await this.generateDicts(); console.log('🔍 验证字典生成结果...'); await this.validateDicts(); console.log('✅ 第11阶段完成 - 字典生成和验证成功'); // 第12阶段:生成模块文件(依赖所有组件) console.log('📊 第12阶段:生成模块文件...'); await this.generateModuleFiles(); console.log('🔍 验证模块文件生成结果...'); await this.validateModuleFiles(); console.log('✅ 第12阶段完成 - 模块文件生成和验证成功'); // 第13阶段:最终质量检查 console.log('📊 第13阶段:最终质量检查...'); await this.runQualityGate(); console.log('✅ 第13阶段完成 - 质量检查通过'); // 第14阶段:生成统计报告 console.log('📊 第14阶段:生成统计报告...'); this.generateStatsReport(); console.log('✅ 第14阶段完成 - 统计报告生成成功'); } catch (error) { console.error('❌ 迁移过程中发生错误:', error.message); this.stats.errors++; throw error; } finally { this.stats.endTime = new Date(); const duration = this.stats.endTime - this.stats.startTime; console.log(`\n⏱️ 总耗时: ${(duration / 1000).toFixed(2)}秒`); console.log('🎉 完整迁移流程完成!'); } } /** * 加载PHP文件发现结果 */ async loadDiscoveryData() { try { console.log(' 🔍 开始读取发现结果文件:', this.config.discoveryResultPath); // 检查文件是否存在 if (!fs.existsSync(this.config.discoveryResultPath)) { throw new Error(`发现结果文件不存在: ${this.config.discoveryResultPath}`); } // 获取文件大小 const stats = fs.statSync(this.config.discoveryResultPath); console.log(` 📏 文件大小: ${(stats.size / 1024 / 1024).toFixed(2)} MB`); console.log(' 📖 正在读取文件内容...'); const data = fs.readFileSync(this.config.discoveryResultPath, 'utf-8'); console.log(' 🔄 正在解析JSON数据...'); this.discoveryData = JSON.parse(data); // 输出数据统计 const controllers = Object.keys(this.discoveryData.controllers || {}).length; const services = Object.keys(this.discoveryData.services || {}).length; const models = Object.keys(this.discoveryData.models || {}).length; console.log(` 📊 数据统计: 控制器${controllers}个, 服务${services}个, 模型${models}个`); console.log(' ✅ 成功加载PHP文件发现结果'); } catch (error) { console.error(' ❌ 加载发现数据失败:', error.message); throw error; } } /** * 创建完整模块结构 */ async createCompleteModuleStructure() { console.log(' 🏗️ 开始创建模块结构...'); // 获取所有模块 const modules = new Set(); // 从控制器中提取模块 const controllerModules = Object.keys(this.discoveryData.controllers || {}); console.log(` 📁 从控制器提取到 ${controllerModules.length} 个模块:`, controllerModules.slice(0, 5).join(', ') + (controllerModules.length > 5 ? '...' : '')); for (const [moduleName, controllers] of Object.entries(this.discoveryData.controllers)) { console.log(` 🔨 创建控制器模块: ${moduleName}`); modules.add(moduleName); } // 从服务中提取模块 const serviceModules = []; for (const [layerName, services] of Object.entries(this.discoveryData.services)) { for (const [serviceName, serviceInfo] of Object.entries(services)) { const moduleName = this.extractModuleNameFromServicePath(serviceInfo.filePath); if (!modules.has(moduleName)) { serviceModules.push(moduleName); console.log(` 🔨 创建服务模块: ${moduleName}`); } modules.add(moduleName); } } console.log(` 📁 从服务提取到 ${serviceModules.length} 个新模块:`, serviceModules.slice(0, 5).join(', ') + (serviceModules.length > 5 ? '...' : '')); // 从模型中提取模块 const modelModules = []; for (const [moduleName, models] of Object.entries(this.discoveryData.models)) { if (!modules.has(moduleName)) { modelModules.push(moduleName); console.log(` 🔨 创建模型模块: ${moduleName}`); } modules.add(moduleName); } console.log(` 📁 从模型提取到 ${modelModules.length} 个新模块:`, modelModules.slice(0, 5).join(', ') + (modelModules.length > 5 ? '...' : '')); // 创建每个模块的目录结构 console.log(` 📂 开始创建 ${modules.size} 个模块的目录结构...`); let processedCount = 0; for (const moduleName of modules) { processedCount++; console.log(` 📁 [${processedCount}/${modules.size}] 创建模块目录: ${moduleName}`); await this.createModuleStructure(moduleName); } console.log(' ✅ 模块结构创建完成'); } /** * 创建模块结构 - 基于PHP实际存在的层级 */ async createModuleStructure(moduleName) { const modulePath = path.join(this.config.nestjsBasePath, moduleName); // 创建模块目录 if (!fs.existsSync(modulePath)) { fs.mkdirSync(modulePath, { recursive: true }); } // 检查PHP实际存在的层级,只创建对应的目录 const phpLayers = this.getPHPLayersForModule(moduleName); for (const layer of phpLayers) { const fullPath = path.join(modulePath, layer); if (!fs.existsSync(fullPath)) { fs.mkdirSync(fullPath, { recursive: true }); } } } /** * 获取模块在PHP中实际存在的层级 */ getPHPLayersForModule(moduleName) { const layers = []; // 检查控制器层级 if (this.hasPHPControllers(moduleName)) { layers.push('controllers'); if (this.hasPHPAdminControllers(moduleName)) { layers.push('controllers/adminapi'); } if (this.hasPHPApiControllers(moduleName)) { layers.push('controllers/api'); } } // 检查服务层级 if (this.hasPHPServices(moduleName)) { layers.push('services'); if (this.hasPHPAdminServices(moduleName)) { layers.push('services/admin'); } if (this.hasPHPApiServices(moduleName)) { layers.push('services/api'); } if (this.hasPHPCoreServices(moduleName)) { layers.push('services/core'); } } // 检查实体层级 if (this.hasPHPModels(moduleName)) { layers.push('entity'); } // 检查验证器层级 if (this.hasPHPValidators(moduleName)) { layers.push('dto'); if (this.hasPHPAdminValidators(moduleName)) { layers.push('dto/admin'); } if (this.hasPHPApiValidators(moduleName)) { layers.push('dto/api'); } } return layers; } /** * 智能分类:判断模块应该迁移到Core层还是跳过 */ classifyModule(moduleName, phpFilePath) { const BusinessLogicConverter = require('./generators/business-logic-converter'); const businessLogicConverter = new BusinessLogicConverter(); const className = path.basename(phpFilePath, '.php'); // 读取文件内容用于智能分析 let content = ''; try { content = fs.readFileSync(phpFilePath, 'utf-8'); } catch (error) { console.warn(`⚠️ 无法读取文件 ${phpFilePath}: ${error.message}`); content = ''; } const classification = businessLogicConverter.classifyFile(phpFilePath, className, content); return { moduleName, classification, // 'CORE_BUSINESS' | 'INFRASTRUCTURE' shouldMigrate: classification === 'CORE_BUSINESS', skipReason: classification === 'INFRASTRUCTURE' ? '属于基础设施,使用Common层服务' : null }; } /** * 检查模块是否有PHP控制器 */ hasPHPControllers(moduleName) { const adminPath = path.join(this.config.phpBasePath, 'app/adminapi/controller', moduleName); const apiPath = path.join(this.config.phpBasePath, 'app/api/controller', moduleName); return fs.existsSync(adminPath) || fs.existsSync(apiPath); } /** * 检查模块是否有PHP管理端控制器 */ hasPHPAdminControllers(moduleName) { const adminPath = path.join(this.config.phpBasePath, 'app/adminapi/controller', moduleName); return fs.existsSync(adminPath); } /** * 检查模块是否有PHP前台控制器 */ hasPHPApiControllers(moduleName) { const apiPath = path.join(this.config.phpBasePath, 'app/api/controller', moduleName); return fs.existsSync(apiPath); } /** * 检查模块是否有PHP服务 */ hasPHPServices(moduleName) { const adminPath = path.join(this.config.phpBasePath, 'app/service/admin', moduleName); const apiPath = path.join(this.config.phpBasePath, 'app/service/api', moduleName); const corePath = path.join(this.config.phpBasePath, 'app/service/core', moduleName); return fs.existsSync(adminPath) || fs.existsSync(apiPath) || fs.existsSync(corePath); } /** * 检查模块是否有PHP管理端服务 */ hasPHPAdminServices(moduleName) { const adminPath = path.join(this.config.phpBasePath, 'app/service/admin', moduleName); return fs.existsSync(adminPath); } /** * 检查模块是否有PHP前台服务 */ hasPHPApiServices(moduleName) { const apiPath = path.join(this.config.phpBasePath, 'app/service/api', moduleName); return fs.existsSync(apiPath); } /** * 检查模块是否有PHP核心服务 */ hasPHPCoreServices(moduleName) { const corePath = path.join(this.config.phpBasePath, 'app/service/core', moduleName); return fs.existsSync(corePath); } /** * 检查模块是否有PHP模型 */ hasPHPModels(moduleName) { const modelPath = path.join(this.config.phpBasePath, 'app/model', moduleName); return fs.existsSync(modelPath); } /** * 检查模块是否有PHP验证器 */ hasPHPValidators(moduleName) { const adminPath = path.join(this.config.phpBasePath, 'app/adminapi/validate', moduleName); const apiPath = path.join(this.config.phpBasePath, 'app/api/validate', moduleName); return fs.existsSync(adminPath) || fs.existsSync(apiPath); } /** * 检查模块是否有PHP管理端验证器 */ hasPHPAdminValidators(moduleName) { const adminPath = path.join(this.config.phpBasePath, 'app/adminapi/validate', moduleName); return fs.existsSync(adminPath); } /** * 检查模块是否有PHP前台验证器 */ hasPHPApiValidators(moduleName) { const apiPath = path.join(this.config.phpBasePath, 'app/api/validate', moduleName); return fs.existsSync(apiPath); } /** * 智能分类生成控制器文件 */ async generateControllersWithClassification() { console.log('🔍 开始智能分类分析...'); const classificationResults = []; const modulesToMigrate = []; // 分析所有模块 for (const moduleName in this.discoveryData.controllers) { const controllers = this.discoveryData.controllers[moduleName]; for (const controllerName in controllers) { const controllerInfo = controllers[controllerName]; const classification = this.classifyModule(moduleName, controllerInfo.filePath); classificationResults.push({ file: controllerInfo.filePath, module: moduleName, controller: controllerName, classification: classification.classification, shouldMigrate: classification.shouldMigrate, skipReason: classification.skipReason }); if (classification.shouldMigrate) { modulesToMigrate.push(moduleName); } } } // 生成分类报告 console.log('\n📋 智能分类结果:'); console.log('='.repeat(80)); const businessModules = classificationResults.filter(r => r.classification === 'CORE_BUSINESS'); const infrastructureModules = classificationResults.filter(r => r.classification === 'INFRASTRUCTURE'); console.log(`✅ 业务模块 (需要迁移到Core层): ${businessModules.length}个`); businessModules.forEach(r => console.log(` - ${r.module}/${r.controller}`)); console.log(`⚠️ 基础设施模块 (使用Common层): ${infrastructureModules.length}个`); infrastructureModules.forEach(r => console.log(` - ${r.module}/${r.controller} (${r.skipReason})`)); console.log('\n🚀 开始生成业务模块...'); // 只迁移业务模块 const uniqueModules = [...new Set(modulesToMigrate)]; for (const moduleName of uniqueModules) { console.log(`📁 生成模块: ${moduleName}`); await this.generateControllersForModule(moduleName); } console.log('✅ 智能分类控制器生成完成!'); return { classificationResults, businessModules, infrastructureModules }; } /** * 为指定模块生成控制器 */ async generateControllersForModule(moduleName) { if (!this.hasPHPControllers(moduleName)) return; const controllerGenerator = new ControllerGenerator(); await controllerGenerator.run(); this.stats.generatedControllers++; } /** * 生成控制器 */ async generateControllers() { const controllerGenerator = new ControllerGenerator(); await controllerGenerator.run(); } /** * 生成服务 */ async generateServices() { const serviceGenerator = new ServiceGenerator(); await serviceGenerator.run(); } /** * 生成实体 */ async generateEntities() { console.log(' 🔨 生成实体文件...'); let processedCount = 0; for (const [moduleName, models] of Object.entries(this.discoveryData.models)) { console.log(` 📁 处理模块: ${moduleName}, 模型数量: ${Object.keys(models).length}`); for (const [modelName, modelInfo] of Object.entries(models)) { console.log(` 📊 处理模型: ${modelName}`); try { await this.createEntity(moduleName, modelName, modelInfo); processedCount++; console.log(` ✅ 成功创建实体: ${moduleName}/${modelName}`); } catch (error) { console.error(` ❌ 创建实体失败 ${moduleName}/${modelName}:`, error.message); this.stats.errors++; } } } console.log(` ✅ 创建了 ${processedCount} 个实体`); } /** * 创建实体 */ async createEntity(moduleName, modelName, modelInfo) { const entityPath = path.join( this.config.nestjsBasePath, moduleName, 'entity', `${this.toKebabCase(modelName)}.entity.ts` ); // 确保目录存在 const entityDir = path.dirname(entityPath); if (!this.config.dryRun && !fs.existsSync(entityDir)) { fs.mkdirSync(entityDir, { recursive: true }); } // 生成实体内容 const entityContent = this.generateEntityContent(moduleName, modelName, modelInfo); // 写入文件 if (!this.config.dryRun) fs.writeFileSync(entityPath, entityContent); console.log(` ✅ 创建实体: ${moduleName}/${this.toKebabCase(modelName)}.entity.ts`); } /** * 转换为kebab-case */ toKebabCase(str) { return String(str) .replace(/([a-z0-9])([A-Z])/g, '$1-$2') .replace(/_/g, '-') .toLowerCase(); } /** * 生成实体内容 */ generateEntityContent(moduleName, modelName, modelInfo) { const className = this.toPascalCase(modelName); return `import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm'; @Entity('${this.toSnakeCase(modelName)}') export class ${className} { @PrimaryGeneratedColumn() id: number; @Column({ type: 'varchar', length: 255, nullable: true }) name: string; @Column({ type: 'text', nullable: true }) description: string; @CreateDateColumn() createdAt: Date; @UpdateDateColumn() updatedAt: Date; } `; } /** * 生成验证器 */ async generateValidators() { const validatorGenerator = new ValidatorGenerator(); await validatorGenerator.run(); } /** * 生成中间件 */ async generateMiddlewares() { // const middlewareGenerator = new MiddlewareGenerator(); // 已废弃,使用Core层Guards+Interceptors+Pipes // await middlewareGenerator.run(); } /** * 生成路由 */ async generateRoutes() { const routeGenerator = new RouteGenerator(); await routeGenerator.run(); } /** * 生成任务 */ async generateJobs() { const jobGenerator = new JobGenerator(); await jobGenerator.run(); } /** * 生成监听器 */ async generateListeners() { const listenerGenerator = new ListenerGenerator(); await listenerGenerator.run(); } /** * 生成命令 */ async generateCommands() { // const commandGenerator = new CommandGenerator(); // 文件不存在,暂时跳过 // await commandGenerator.run(); console.log(' ⏭️ 跳过命令生成 (文件不存在)'); } /** * 生成特征 - 已废弃 * 原因:PHP项目只有2个Trait文件,NestJS不支持Trait概念 * 应改用 Injectable Service 模式 */ async generateTraits() { console.log(' ⏭️ 跳过特征生成 (已废弃:建议使用 Injectable Service)'); } /** * 生成字典 */ async generateDicts() { const dictGenerator = new DictGenerator(); await dictGenerator.run(); } /** * 生成模块文件 */ async generateModuleFiles() { console.log(' 🔨 生成模块文件...'); // 获取所有模块 const modules = new Set(); // 从发现数据中提取模块名 if (this.discoveryData && this.discoveryData.modules) { Object.keys(this.discoveryData.modules).forEach(moduleName => { modules.add(moduleName); }); } // 从控制器中提取模块名 if (this.discoveryData && this.discoveryData.controllers) { Object.keys(this.discoveryData.controllers).forEach(controllerPath => { const pathParts = controllerPath.split('/'); if (pathParts.length > 0) { modules.add(pathParts[0]); } }); } // 从服务中提取模块名 if (this.discoveryData && this.discoveryData.services) { Object.keys(this.discoveryData.services).forEach(servicePath => { const pathParts = servicePath.split('/'); if (pathParts.length > 0) { modules.add(pathParts[0]); } }); } const moduleArray = Array.from(modules); for (const moduleName of moduleArray) { await this.createModuleFile(moduleName); } console.log(' ✅ 模块文件生成完成'); } /** * 创建模块文件 */ async createModuleFile(moduleName) { const moduleDir = path.join(this.config.nestjsBasePath, moduleName); const modulePath = path.join(moduleDir, `${moduleName}.module.ts`); // 确保目录存在 if (!fs.existsSync(moduleDir)) { fs.mkdirSync(moduleDir, { recursive: true }); } const content = this.generateModuleContent(moduleName); fs.writeFileSync(modulePath, content); console.log(` ✅ 创建模块: ${moduleName}/${moduleName}.module.ts`); } /** * 生成模块内容 */ generateModuleContent(moduleName) { const className = `${this.toPascalCase(moduleName)}Module`; return `import { Module } from '@nestjs/common'; @Module({ imports: [], controllers: [], providers: [], exports: [], }) export class ${className} {} `; } /** * 从服务路径提取模块名 */ extractModuleNameFromServicePath(filePath) { const pathParts = filePath.split('/'); const serviceIndex = pathParts.findIndex(part => part === 'service'); if (serviceIndex > 0) { return pathParts[serviceIndex - 1]; } const fileName = path.basename(filePath, '.php'); if (fileName.includes('Service')) { return fileName.replace('Service', '').toLowerCase(); } return 'unknown'; } /** * 转换为驼峰命名 */ toCamelCase(str) { return str.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => { return index === 0 ? word.toLowerCase() : word.toUpperCase(); }).replace(/\s+/g, ''); } /** * 转换为帕斯卡命名 - 处理连字符 */ toPascalCase(str) { return str.replace(/(^|-)([a-z])/g, (match, p1, p2) => p2.toUpperCase()); } /** * 转换为蛇形命名 */ toSnakeCase(str) { return str.replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, ''); } /** * 运行 Quality Gate 质量检查 */ async runQualityGate() { try { const qualityGate = new QualityGate(path.dirname(this.config.nestjsBasePath)); const passed = await qualityGate.run(); if (passed) { console.log(' ✅ Quality Gate 通过'); this.stats.completedSteps++; } else { console.log(' ❌ Quality Gate 失败'); this.stats.failedSteps++; // Quality Gate 失败不中断流程,但记录错误 console.log(' ⚠️ 继续执行,但建议修复质量问题'); } } catch (error) { console.log(` ⚠️ Quality Gate 检查失败: ${error.message}`); console.log(' ℹ️ 跳过质量检查,继续执行迁移流程'); this.stats.failedSteps++; } } /** * 生成统计报告 */ generateStatsReport() { console.log('\n📊 完整迁移统计报告'); console.log('='.repeat(50)); console.log(`✅ 完成步骤: ${this.stats.completedSteps}`); console.log(`❌ 失败步骤: ${this.stats.failedSteps}`); console.log(`📈 成功率: ${this.stats.completedSteps > 0 ? ((this.stats.completedSteps - this.stats.failedSteps) / this.stats.completedSteps * 100).toFixed(2) : 0}%`); console.log(`⏱️ 总耗时: ${this.stats.endTime ? ((this.stats.endTime - this.stats.startTime) / 1000).toFixed(2) : 0}秒`); } /** * 验证实体生成结果 */ async validateEntities() { try { const entityFiles = this.findFilesByPattern('**/*.entity.ts'); console.log(` 📊 验证 ${entityFiles.length} 个实体文件...`); let validCount = 0; let errorCount = 0; for (const file of entityFiles) { try { const content = fs.readFileSync(file, 'utf8'); if (content.includes('@Entity') && content.includes('export class')) { validCount++; } else { console.log(` ⚠️ 实体文件格式异常: ${file}`); errorCount++; } } catch (error) { console.log(` ❌ 实体文件读取失败: ${file} - ${error.message}`); errorCount++; } } console.log(` ✅ 实体验证完成: ${validCount}个有效, ${errorCount}个错误`); return errorCount === 0; } catch (error) { console.log(` ❌ 实体验证失败: ${error.message}`); return false; } } /** * 验证服务生成结果 */ async validateServices() { try { const serviceFiles = this.findFilesByPattern('**/*.service.ts'); console.log(` 📊 验证 ${serviceFiles.length} 个服务文件...`); let validCount = 0; let errorCount = 0; for (const file of serviceFiles) { try { const content = fs.readFileSync(file, 'utf8'); if (content.includes('@Injectable') && content.includes('export class')) { // 检查是否有语法错误 if (content.includes(']]') || content.includes('BusinessBusinessException')) { console.log(` ⚠️ 服务文件有语法错误: ${file}`); errorCount++; } else { validCount++; } } else { console.log(` ⚠️ 服务文件格式异常: ${file}`); errorCount++; } } catch (error) { console.log(` ❌ 服务文件读取失败: ${file} - ${error.message}`); errorCount++; } } console.log(` ✅ 服务验证完成: ${validCount}个有效, ${errorCount}个错误`); return errorCount === 0; } catch (error) { console.log(` ❌ 服务验证失败: ${error.message}`); return false; } } /** * 验证验证器生成结果 */ async validateValidators() { try { const validatorFiles = this.findFilesByPattern('**/*.validator.ts'); console.log(` 📊 验证 ${validatorFiles.length} 个验证器文件...`); let validCount = 0; let errorCount = 0; for (const file of validatorFiles) { try { const content = fs.readFileSync(file, 'utf8'); if (content.includes('export class') && content.includes('validate')) { validCount++; } else { console.log(` ⚠️ 验证器文件格式异常: ${file}`); errorCount++; } } catch (error) { console.log(` ❌ 验证器文件读取失败: ${file} - ${error.message}`); errorCount++; } } console.log(` ✅ 验证器验证完成: ${validCount}个有效, ${errorCount}个错误`); return errorCount === 0; } catch (error) { console.log(` ❌ 验证器验证失败: ${error.message}`); return false; } } /** * 验证控制器生成结果 */ async validateControllers() { try { const controllerFiles = this.findFilesByPattern('**/*.controller.ts'); console.log(` 📊 验证 ${controllerFiles.length} 个控制器文件...`); let validCount = 0; let errorCount = 0; for (const file of controllerFiles) { try { const content = fs.readFileSync(file, 'utf8'); if (content.includes('@Controller') && content.includes('export class')) { validCount++; } else { console.log(` ⚠️ 控制器文件格式异常: ${file}`); errorCount++; } } catch (error) { console.log(` ❌ 控制器文件读取失败: ${file} - ${error.message}`); errorCount++; } } console.log(` ✅ 控制器验证完成: ${validCount}个有效, ${errorCount}个错误`); return errorCount === 0; } catch (error) { console.log(` ❌ 控制器验证失败: ${error.message}`); return false; } } /** * 验证路由生成结果 */ async validateRoutes() { try { const routeFiles = this.findFilesByPattern('**/*.routes.ts'); console.log(` 📊 验证 ${routeFiles.length} 个路由文件...`); let validCount = 0; let errorCount = 0; for (const file of routeFiles) { try { const content = fs.readFileSync(file, 'utf8'); if (content.includes('export') && content.includes('Routes')) { validCount++; } else { console.log(` ⚠️ 路由文件格式异常: ${file}`); errorCount++; } } catch (error) { console.log(` ❌ 路由文件读取失败: ${file} - ${error.message}`); errorCount++; } } console.log(` ✅ 路由验证完成: ${validCount}个有效, ${errorCount}个错误`); return errorCount === 0; } catch (error) { console.log(` ❌ 路由验证失败: ${error.message}`); return false; } } /** * 验证任务生成结果 */ async validateJobs() { try { const jobFiles = this.findFilesByPattern('**/*.job.ts'); console.log(` 📊 验证 ${jobFiles.length} 个任务文件...`); let validCount = 0; let errorCount = 0; for (const file of jobFiles) { try { const content = fs.readFileSync(file, 'utf8'); if (content.includes('@Processor') && content.includes('export class')) { validCount++; } else { console.log(` ⚠️ 任务文件格式异常: ${file}`); errorCount++; } } catch (error) { console.log(` ❌ 任务文件读取失败: ${file} - ${error.message}`); errorCount++; } } console.log(` ✅ 任务验证完成: ${validCount}个有效, ${errorCount}个错误`); return errorCount === 0; } catch (error) { console.log(` ❌ 任务验证失败: ${error.message}`); return false; } } /** * 验证监听器生成结果 */ async validateListeners() { try { const listenerFiles = this.findFilesByPattern('**/*.listener.ts'); console.log(` 📊 验证 ${listenerFiles.length} 个监听器文件...`); let validCount = 0; let errorCount = 0; for (const file of listenerFiles) { try { const content = fs.readFileSync(file, 'utf8'); if (content.includes('@OnEvent') && content.includes('export class')) { validCount++; } else { console.log(` ⚠️ 监听器文件格式异常: ${file}`); errorCount++; } } catch (error) { console.log(` ❌ 监听器文件读取失败: ${file} - ${error.message}`); errorCount++; } } console.log(` ✅ 监听器验证完成: ${validCount}个有效, ${errorCount}个错误`); return errorCount === 0; } catch (error) { console.log(` ❌ 监听器验证失败: ${error.message}`); return false; } } /** * 验证命令生成结果 */ async validateCommands() { try { const commandFiles = this.findFilesByPattern('**/*.command.ts'); console.log(` 📊 验证 ${commandFiles.length} 个命令文件...`); let validCount = 0; let errorCount = 0; for (const file of commandFiles) { try { const content = fs.readFileSync(file, 'utf8'); if (content.includes('@Command') && content.includes('export class')) { validCount++; } else { console.log(` ⚠️ 命令文件格式异常: ${file}`); errorCount++; } } catch (error) { console.log(` ❌ 命令文件读取失败: ${file} - ${error.message}`); errorCount++; } } console.log(` ✅ 命令验证完成: ${validCount}个有效, ${errorCount}个错误`); return errorCount === 0; } catch (error) { console.log(` ❌ 命令验证失败: ${error.message}`); return false; } } /** * 验证字典生成结果 */ async validateDicts() { try { const dictFiles = this.findFilesByPattern('**/*.enum.ts'); console.log(` 📊 验证 ${dictFiles.length} 个字典文件...`); let validCount = 0; let errorCount = 0; for (const file of dictFiles) { try { const content = fs.readFileSync(file, 'utf8'); if (content.includes('export enum') || content.includes('export const')) { validCount++; } else { console.log(` ⚠️ 字典文件格式异常: ${file}`); errorCount++; } } catch (error) { console.log(` ❌ 字典文件读取失败: ${file} - ${error.message}`); errorCount++; } } console.log(` ✅ 字典验证完成: ${validCount}个有效, ${errorCount}个错误`); return errorCount === 0; } catch (error) { console.log(` ❌ 字典验证失败: ${error.message}`); return false; } } /** * 验证模块文件生成结果 */ async validateModuleFiles() { try { const moduleFiles = this.findFilesByPattern('**/*.module.ts'); console.log(` 📊 验证 ${moduleFiles.length} 个模块文件...`); let validCount = 0; let errorCount = 0; for (const file of moduleFiles) { try { const content = fs.readFileSync(file, 'utf8'); if (content.includes('@Module') && content.includes('export class')) { validCount++; } else { console.log(` ⚠️ 模块文件格式异常: ${file}`); errorCount++; } } catch (error) { console.log(` ❌ 模块文件读取失败: ${file} - ${error.message}`); errorCount++; } } console.log(` ✅ 模块文件验证完成: ${validCount}个有效, ${errorCount}个错误`); return errorCount === 0; } catch (error) { console.log(` ❌ 模块文件验证失败: ${error.message}`); return false; } } /** * 查找匹配模式的文件 */ findFilesByPattern(pattern) { try { const glob = require('glob'); const searchPath = path.join(this.config.nestjsBasePath, pattern); return glob.sync(searchPath); } catch (error) { // 如果glob模块不存在,使用简单的文件系统搜索 console.log(` ⚠️ glob模块不可用,使用简单文件搜索: ${error.message}`); return this.findFilesByPatternSimple(pattern); } } /** * 简单的文件搜索(当glob不可用时) */ findFilesByPatternSimple(pattern) { const files = []; const searchDir = this.config.nestjsBasePath; if (!fs.existsSync(searchDir)) { return files; } const walkDir = (dir) => { const items = fs.readdirSync(dir); for (const item of items) { const fullPath = path.join(dir, item); const stat = fs.statSync(fullPath); if (stat.isDirectory()) { walkDir(fullPath); } else if (stat.isFile() && item.endsWith('.ts')) { const relativePath = path.relative(this.config.nestjsBasePath, fullPath); if (this.matchesPattern(relativePath, pattern)) { files.push(fullPath); } } } }; walkDir(searchDir); return files; } /** * 简单的模式匹配 */ matchesPattern(filePath, pattern) { // 将glob模式转换为简单的字符串匹配 const simplePattern = pattern .replace(/\*\*/g, '') .replace(/\*/g, '') .replace(/\.ts$/, ''); return filePath.includes(simplePattern); } } // 如果直接运行此文件 if (require.main === module) { const coordinator = new MigrationCoordinator(); coordinator.run().catch(console.error); } module.exports = MigrationCoordinator;