Files
wwjcloud-nest-v1/tools-v1/java-tools/generators/module-generator.js
wanwujie 699680c93a feat: 重构v1框架架构和清理整理
- 将preset.ts移动到config目录,符合架构规范
- 迁移php-tools到java-tools,参考Java架构而非PHP
- 清理AI层文档,整合为单一README
- 删除core层,专注boot和ai层
- 集成AI层与Boot层,实现100%组件集成
- 清理废弃js文件和临时报告文件
- 更新导入路径,保持代码一致性
2025-10-20 23:07:37 +08:00

555 lines
16 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const fs = require('fs');
const path = require('path');
/**
* NestJS模块生成器 (参考Java架构)
* 为每个模块创建对应的.module.ts文件并正确引用所有组件
*/
class ModuleGenerator {
constructor() {
this.config = {
javaBasePath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/niucloud-java/niucloud-core/src/main/java',
nestjsBasePath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-core/src',
discoveryResultPath: './java-discovery-result.json',
whitelistModules: [], // 空数组=全部业务模块,结合黑名单过滤
blacklistModules: ['job','queue','workerman','lang','menu','system'],
includeTypeOrmFeature: true
};
this.discoveryData = null;
this.stats = {
createdModules: 0,
updatedModules: 0,
errors: 0
};
}
/**
* 运行模块生成
*/
async run() {
try {
console.log('🚀 启动NestJS模块生成器...');
console.log('目标:为每个模块创建.module.ts文件并正确引用所有组件\n');
// 第1阶段加载Java架构发现结果含PHP业务逻辑
console.log('📊 第1阶段加载Java架构发现结果含PHP业务逻辑...');
await this.loadDiscoveryData();
console.log(' ✅ 成功加载Java架构发现结果含PHP业务逻辑');
// 第2阶段扫描现有文件结构
console.log('\n📊 第2阶段扫描现有文件结构...');
const moduleStructure = await this.scanModuleStructure();
console.log(` ✅ 扫描了 ${Object.keys(moduleStructure).length} 个模块`);
// 第3阶段生成模块文件
console.log('\n📊 第3阶段生成模块文件...');
await this.generateModules(moduleStructure);
console.log(` ✅ 生成了 ${this.stats.createdModules} 个模块文件`);
// 第4阶段生成统计报告
console.log('\n📊 第4阶段生成统计报告...');
this.generateStatsReport();
} catch (error) {
console.error('❌ 生成过程中发生错误:', error.message);
this.stats.errors++;
throw error;
}
}
/**
* 加载Java架构发现结果含PHP业务逻辑
*/
async loadDiscoveryData() {
try {
const data = fs.readFileSync(this.config.discoveryResultPath, 'utf8');
this.discoveryData = JSON.parse(data);
} catch (error) {
console.log(` ⚠️ 未找到发现结果文件,跳过加载: ${error.message}`);
this.discoveryData = {};
}
}
/**
* 扫描模块结构
*/
async scanModuleStructure() {
const moduleStructure = {};
const commonPath = this.config.nestjsBasePath;
if (!fs.existsSync(commonPath)) {
console.log(' ⚠️ common目录不存在');
return moduleStructure;
}
const modules = fs.readdirSync(commonPath, { withFileTypes: true })
.filter(dirent => dirent.isDirectory())
.map(dirent => dirent.name);
for (const moduleName of modules) {
if (this.shouldSkipModule(moduleName)) {
console.log(` ⏭️ 跳过非业务模块: ${moduleName}`);
continue;
}
const modulePath = path.join(commonPath, moduleName);
moduleStructure[moduleName] = {
controllers: this.scanControllers(modulePath),
services: this.scanServices(modulePath),
entities: this.scanEntities(modulePath),
validators: this.scanValidators(modulePath),
middlewares: this.scanMiddlewares(modulePath),
jobs: this.scanJobs(modulePath),
listeners: this.scanListeners(modulePath),
commands: this.scanCommands(modulePath),
dicts: this.scanDicts(modulePath)
};
}
return moduleStructure;
}
/**
* 读取实际文件中的类名
*/
getActualClassName(filePath) {
try {
if (!fs.existsSync(filePath)) {
return null;
}
const content = fs.readFileSync(filePath, 'utf8');
const match = content.match(/export\s+(?:class|interface|enum)\s+(\w+)/);
return match ? match[1] : null;
} catch (error) {
console.error(`读取文件 ${filePath} 时出错:`, error.message);
return null;
}
}
/**
* 扫描控制器
*/
scanControllers(modulePath) {
const controllers = [];
const controllersPath = path.join(modulePath, 'controllers');
if (fs.existsSync(controllersPath)) {
const layers = ['adminapi', 'api'];
for (const layer of layers) {
const layerPath = path.join(controllersPath, layer);
if (fs.existsSync(layerPath)) {
const allFiles = fs.readdirSync(layerPath);
const controllerFiles = allFiles.filter(file => file.endsWith('.controller.ts'));
if (controllerFiles.length > 0) {
console.log(` 发现 ${layer} 层控制器: ${controllerFiles.join(', ')}`);
}
const files = controllerFiles.map(file => {
const filePath = path.join(layerPath, file);
const actualClassName = this.getActualClassName(filePath);
return {
name: actualClassName || this.guessControllerClassName(file),
path: `./controllers/${layer}/${file}`,
layer: layer
};
});
controllers.push(...files);
}
}
}
return controllers;
}
/**
* 扫描服务
*/
scanServices(modulePath) {
const services = [];
const servicesPath = path.join(modulePath, 'services');
if (fs.existsSync(servicesPath)) {
const layers = ['admin', 'api', 'core'];
for (const layer of layers) {
const layerPath = path.join(servicesPath, layer);
if (fs.existsSync(layerPath)) {
const files = fs.readdirSync(layerPath)
.filter(file => file.endsWith('.service.ts'))
.map(file => {
const filePath = path.join(layerPath, file);
const actualClassName = this.getActualClassName(filePath);
return {
name: actualClassName || this.guessServiceClassName(file, layer),
path: `./services/${layer}/${file}`,
layer: layer
};
});
services.push(...files);
}
}
}
return services;
}
/**
* 扫描实体
*/
scanEntities(modulePath) {
const entities = [];
const entitiesPath = path.join(modulePath, 'entity');
if (fs.existsSync(entitiesPath)) {
const files = fs.readdirSync(entitiesPath)
.filter(file => file.endsWith('.entity.ts'))
.map(file => ({
name: this.getActualClassName(path.join(entitiesPath, file)) || this.guessEntityClassName(file),
path: `./entity/${file}`
}));
entities.push(...files);
}
return entities;
}
/**
* 扫描验证器
*/
scanValidators(modulePath) {
const validators = [];
const validatorsPath = path.join(modulePath, 'dto');
if (fs.existsSync(validatorsPath)) {
const files = fs.readdirSync(validatorsPath, { recursive: true })
.filter(file => file.endsWith('.ts') && !file.endsWith('.d.ts'))
.map(file => ({
name: file.replace('.ts', ''),
path: `./dto/${file}`
}));
validators.push(...files);
}
return validators;
}
/**
* 扫描中间件
*/
scanMiddlewares(modulePath) {
const middlewares = [];
const middlewaresPath = path.join(modulePath, 'guards');
if (fs.existsSync(middlewaresPath)) {
const files = fs.readdirSync(middlewaresPath)
.filter(file => file.endsWith('.ts') && !file.endsWith('.d.ts'))
.map(file => ({
name: file.replace('.ts', ''),
path: `./guards/${file}`
}));
middlewares.push(...files);
}
return middlewares;
}
/**
* 扫描任务
*/
scanJobs(modulePath) {
const jobs = [];
const jobsPath = path.join(modulePath, 'jobs');
if (fs.existsSync(jobsPath)) {
const files = fs.readdirSync(jobsPath)
.filter(file => file.endsWith('.ts') && !file.endsWith('.d.ts'))
.map(file => ({
name: file.replace('.ts', ''),
path: `./jobs/${file}`
}));
jobs.push(...files);
}
return jobs;
}
/**
* 扫描监听器
*/
scanListeners(modulePath) {
const listeners = [];
const listenersPath = path.join(modulePath, 'listeners');
if (fs.existsSync(listenersPath)) {
const files = fs.readdirSync(listenersPath)
.filter(file => file.endsWith('.ts') && !file.endsWith('.d.ts'))
.map(file => ({
name: file.replace('.ts', ''),
path: `./listeners/${file}`
}));
listeners.push(...files);
}
return listeners;
}
/**
* 扫描命令
*/
scanCommands(modulePath) {
const commands = [];
const commandsPath = path.join(modulePath, 'commands');
if (fs.existsSync(commandsPath)) {
const files = fs.readdirSync(commandsPath)
.filter(file => file.endsWith('.ts') && !file.endsWith('.d.ts'))
.map(file => ({
name: file.replace('.ts', ''),
path: `./commands/${file}`
}));
commands.push(...files);
}
return commands;
}
/**
* 扫描字典
*/
scanDicts(modulePath) {
const dicts = [];
const dictsPath = path.join(modulePath, 'dicts');
if (fs.existsSync(dictsPath)) {
const files = fs.readdirSync(dictsPath)
.filter(file => file.endsWith('.ts') && !file.endsWith('.d.ts'))
.map(file => ({
name: file.replace('.ts', ''),
path: `./dicts/${file}`
}));
dicts.push(...files);
}
return dicts;
}
/**
* 生成模块文件
*/
async generateModules(moduleStructure) {
console.log(' 🔨 生成模块文件...');
for (const [moduleName, components] of Object.entries(moduleStructure)) {
try {
await this.generateModuleFile(moduleName, components);
this.stats.createdModules++;
} catch (error) {
console.error(` ❌ 生成模块 ${moduleName} 失败:`, error.message);
this.stats.errors++;
}
}
}
/**
* 生成单个模块文件
*/
async generateModuleFile(moduleName, components) {
const modulePath = path.join(this.config.nestjsBasePath, moduleName, `${moduleName}.module.ts`);
// 生成模块内容
const moduleContent = this.generateModuleContent(moduleName, components);
// 确保目录存在
this.ensureDir(path.dirname(modulePath));
// 写入文件
fs.writeFileSync(modulePath, moduleContent);
console.log(` ✅ 创建模块: ${moduleName}/${moduleName}.module.ts`);
}
/**
* 生成模块内容
*/
generateModuleContent(moduleName, components) {
const className = this.toPascalCase(moduleName) + 'Module';
let imports = [];
let controllers = [];
let providers = [];
let exports = [];
let importSet = new Set(); // 用于去重
// TypeORM feature (可选)
const entityClassNames = components.entities.map(e => e.name).filter(Boolean);
if (this.config.includeTypeOrmFeature && entityClassNames.length > 0) {
importSet.add(`import { TypeOrmModule } from '@nestjs/typeorm';`);
imports.push(`TypeOrmModule.forFeature([${entityClassNames.join(', ')}])`);
}
// 导入控制器并注册
for (const controller of components.controllers) {
importSet.add(`import { ${controller.name} } from '${controller.path}';`);
controllers.push(controller.name);
}
// 导入服务并注册
for (const service of components.services) {
if (!importSet.has(`import { ${service.name} } from '${service.path}';`)) {
importSet.add(`import { ${service.name} } from '${service.path}';`);
providers.push(`${service.name}`);
}
}
// 导入实体(如果需要)
for (const entity of components.entities) {
if (!importSet.has(`import { ${entity.name} } from '${entity.path}';`)) {
importSet.add(`import { ${entity.name} } from '${entity.path}';`);
}
}
// 组合最终内容
const moduleContent = `${Array.from(importSet).join('\n')}
import { Module } from '@nestjs/common';
@Module({
imports: [${imports.join(', ')}],
controllers: [${controllers.join(', ')}],
providers: [${providers.join(', ')}],
exports: [${exports.join(', ')}],
})
export class ${className} {}
`;
return moduleContent;
}
/**
* 从文件内容获取导出的类名
*/
getActualClassName(filePath) {
try {
if (!fs.existsSync(filePath)) return null;
const content = fs.readFileSync(filePath, 'utf8');
const match = content.match(/export\s+class\s+(\w+)/);
return match ? match[1] : null;
} catch (error) {
return null;
}
}
/**
* 由 kebab-case 实体文件名推测类名
* 例如: member.entity.ts -> MemberEntity
*/
guessEntityClassName(fileName) {
const base = fileName.replace(/\.entity\.ts$/i, '');
return this.kebabToPascal(base) + 'Entity';
}
/**
* 由 kebab-case 控制器文件名推测类名
* 例如: member-level.controller.ts -> MemberLevelController
*/
guessControllerClassName(fileName) {
const base = fileName.replace(/\.controller\.ts$/i, '');
return this.kebabToPascal(base) + 'Controller';
}
/**
* 由 kebab-case 服务文件名推测类名
* 例如: member-level.service.ts -> MemberLevelService
*/
guessServiceClassName(fileName, layer) {
const base = fileName.replace(/\.service\.ts$/i, '');
return this.kebabToPascal(base) + 'Service';
}
/**
* 确保目录存在
*/
ensureDir(dirPath) {
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
}
}
/**
* 转换为PascalCase
*/
toPascalCase(str) {
return str.replace(/(^|_)([a-z])/g, (match, p1, p2) => p2.toUpperCase());
}
/**
* kebab-case 转 PascalCase
*/
kebabToPascal(str) {
return str
.split('-')
.filter(Boolean)
.map(s => s.charAt(0).toUpperCase() + s.slice(1))
.join('');
}
shouldSkipModule(moduleName) {
if (this.config.whitelistModules && this.config.whitelistModules.length > 0) {
if (!this.config.whitelistModules.includes(moduleName)) return true;
}
if (this.config.blacklistModules && this.config.blacklistModules.includes(moduleName)) {
return true;
}
return false;
}
/**
* 获取层前缀
*/
getLayerPrefix(layer, serviceName) {
// 如果服务名已经包含Core前缀则不需要再添加
if (layer === 'core' && serviceName.toLowerCase().startsWith('core')) {
return '';
}
const layerMap = {
'admin': 'Admin',
'api': 'Api',
'core': 'Core'
};
return layerMap[layer] || '';
}
/**
* 检查是否需要别名
*/
needsAlias(layer, serviceName) {
// 如果服务名已经包含层前缀,则不需要别名
if (layer === 'core' && serviceName.toLowerCase().startsWith('core')) {
return false;
}
return true;
}
/**
* 生成统计报告
*/
generateStatsReport() {
console.log('\n📊 NestJS模块生成统计报告:');
console.log('============================================================');
console.log(` 📁 创建模块: ${this.stats.createdModules}`);
console.log(` 🔄 更新模块: ${this.stats.updatedModules}`);
console.log(` ❌ 错误数量: ${this.stats.errors}`);
console.log('============================================================');
console.log('\n✅ 🎉 NestJS模块生成完成');
}
}
// 运行模块生成器
if (require.main === module) {
const generator = new ModuleGenerator();
generator.run().catch(console.error);
}
module.exports = ModuleGenerator;