Files
wwjcloud/tools/auto-mapping-checker.js
万物街 127a4db1e3 feat: 完成sys模块迁移,对齐PHP/Java框架
- 重构sys模块架构,严格按admin/api/core分层
- 对齐所有sys实体与数据库表结构
- 实现完整的adminapi控制器,匹配PHP/Java契约
- 修复依赖注入问题,确保服务正确注册
- 添加自动迁移工具和契约验证
- 完善多租户支持和审计功能
- 统一命名规范,与PHP业务逻辑保持一致
2025-09-21 21:29:28 +08:00

374 lines
10 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
/**
* PHP与NestJS项目自动映射检查器
* 检查PHP项目与NestJS项目的模块、控制器、服务等对应关系
*/
const fs = require('fs');
const path = require('path');
class AutoMappingChecker {
constructor() {
this.projectRoot = process.cwd();
this.phpPath = path.join(this.projectRoot, 'niucloud-php/niucloud');
this.nestjsPath = path.join(this.projectRoot, 'wwjcloud/src');
this.results = {
modules: [],
controllers: [],
services: [],
models: [],
summary: {
total: 0,
matched: 0,
missing: 0
}
};
}
/**
* 检查目录是否存在
*/
checkDirectories() {
if (!fs.existsSync(this.phpPath)) {
console.error('❌ PHP项目路径不存在:', this.phpPath);
return false;
}
if (!fs.existsSync(this.nestjsPath)) {
console.error('❌ NestJS项目路径不存在:', this.nestjsPath);
return false;
}
return true;
}
/**
* 获取PHP控制器列表
*/
getPhpControllers() {
const controllers = [];
const adminApiPath = path.join(this.phpPath, 'app/adminapi/controller');
const apiPath = path.join(this.phpPath, 'app/api/controller');
// 扫描管理端控制器
if (fs.existsSync(adminApiPath)) {
this.scanPhpControllers(adminApiPath, 'adminapi', controllers);
}
// 扫描前台控制器
if (fs.existsSync(apiPath)) {
this.scanPhpControllers(apiPath, 'api', controllers);
}
return controllers;
}
/**
* 扫描PHP控制器
*/
scanPhpControllers(dir, type, controllers) {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
// 递归扫描子目录
this.scanPhpControllers(fullPath, type, controllers);
} else if (entry.isFile() && entry.name.endsWith('.php')) {
const relativePath = path.relative(path.join(this.phpPath, 'app', type, 'controller'), fullPath);
const modulePath = path.dirname(relativePath);
const fileName = path.basename(entry.name, '.php');
controllers.push({
type,
module: modulePath === '.' ? 'root' : modulePath,
name: fileName,
phpPath: fullPath,
relativePath
});
}
}
}
/**
* 获取NestJS控制器列表
*/
getNestjsControllers() {
const controllers = [];
const commonPath = path.join(this.nestjsPath, 'common');
if (!fs.existsSync(commonPath)) {
return controllers;
}
const modules = fs.readdirSync(commonPath, { withFileTypes: true })
.filter(entry => entry.isDirectory())
.map(entry => entry.name);
for (const module of modules) {
const modulePath = path.join(commonPath, module);
// 检查adminapi控制器
const adminApiPath = path.join(modulePath, 'controllers/adminapi');
if (fs.existsSync(adminApiPath)) {
this.scanNestjsControllers(adminApiPath, 'adminapi', module, controllers);
}
// 检查api控制器
const apiPath = path.join(modulePath, 'controllers/api');
if (fs.existsSync(apiPath)) {
this.scanNestjsControllers(apiPath, 'api', module, controllers);
}
}
return controllers;
}
/**
* 扫描NestJS控制器
*/
scanNestjsControllers(dir, type, module, controllers) {
if (!fs.existsSync(dir)) return;
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
if (entry.isFile() && entry.name.endsWith('.controller.ts')) {
const fileName = path.basename(entry.name, '.controller.ts');
controllers.push({
type,
module,
name: fileName,
nestjsPath: path.join(dir, entry.name)
});
}
}
}
/**
* 检查控制器映射
*/
checkControllerMapping() {
const phpControllers = this.getPhpControllers();
const nestjsControllers = this.getNestjsControllers();
console.log('\n📋 控制器映射检查结果:');
console.log('='.repeat(50));
for (const phpController of phpControllers) {
const matched = nestjsControllers.find(nestjs =>
nestjs.type === phpController.type &&
this.normalizeModuleName(nestjs.module) === this.normalizeModuleName(phpController.module) &&
this.normalizeControllerName(nestjs.name) === this.normalizeControllerName(phpController.name)
);
const status = matched ? '✅' : '❌';
const moduleDisplay = phpController.module === 'root' ? '/' : phpController.module;
console.log(`${status} ${phpController.type}/${moduleDisplay}/${phpController.name}.php`);
if (matched) {
console.log(`${matched.module}/${matched.name}.controller.ts`);
this.results.summary.matched++;
} else {
console.log(` → 缺失对应的NestJS控制器`);
this.results.summary.missing++;
}
this.results.summary.total++;
this.results.controllers.push({
php: phpController,
nestjs: matched,
matched: !!matched
});
}
}
/**
* 标准化模块名
*/
normalizeModuleName(name) {
if (name === 'root' || name === '.' || name === '/') return '';
return name.toLowerCase().replace(/[_\-]/g, '');
}
/**
* 标准化控制器名
*/
normalizeControllerName(name) {
return name.toLowerCase().replace(/[_\-]/g, '');
}
/**
* 检查服务映射
*/
checkServiceMapping() {
console.log('\n🔧 服务映射检查:');
console.log('='.repeat(50));
const phpServicePath = path.join(this.phpPath, 'app/service');
const nestjsCommonPath = path.join(this.nestjsPath, 'common');
if (!fs.existsSync(phpServicePath)) {
console.log('❌ PHP服务目录不存在');
return;
}
if (!fs.existsSync(nestjsCommonPath)) {
console.log('❌ NestJS通用服务目录不存在');
return;
}
// 简化的服务检查
const phpServices = this.getPhpServices(phpServicePath);
const nestjsServices = this.getNestjsServices(nestjsCommonPath);
for (const phpService of phpServices) {
const matched = nestjsServices.find(nestjs =>
this.normalizeServiceName(nestjs.name) === this.normalizeServiceName(phpService.name)
);
const status = matched ? '✅' : '❌';
console.log(`${status} ${phpService.name}.php`);
if (matched) {
console.log(`${matched.module}/${matched.name}.service.ts`);
}
}
}
/**
* 获取PHP服务列表
*/
getPhpServices(dir) {
const services = [];
if (!fs.existsSync(dir)) return services;
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
if (entry.isFile() && entry.name.endsWith('.php')) {
services.push({
name: path.basename(entry.name, '.php'),
path: path.join(dir, entry.name)
});
}
}
return services;
}
/**
* 获取NestJS服务列表
*/
getNestjsServices(dir) {
const services = [];
if (!fs.existsSync(dir)) return services;
const modules = fs.readdirSync(dir, { withFileTypes: true })
.filter(entry => entry.isDirectory())
.map(entry => entry.name);
for (const module of modules) {
const servicesPath = path.join(dir, module, 'services');
if (fs.existsSync(servicesPath)) {
this.scanNestjsServices(servicesPath, module, services);
}
}
return services;
}
/**
* 扫描NestJS服务
*/
scanNestjsServices(dir, module, services) {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
this.scanNestjsServices(fullPath, module, services);
} else if (entry.isFile() && entry.name.endsWith('.service.ts')) {
services.push({
module,
name: path.basename(entry.name, '.service.ts'),
path: fullPath
});
}
}
}
/**
* 标准化服务名
*/
normalizeServiceName(name) {
return name.toLowerCase().replace(/service$/, '').replace(/[_\-]/g, '');
}
/**
* 生成统计报告
*/
generateSummary() {
console.log('\n📊 检查统计:');
console.log('='.repeat(50));
console.log(`总计检查项: ${this.results.summary.total}`);
console.log(`匹配成功: ${this.results.summary.matched} (${((this.results.summary.matched / this.results.summary.total) * 100).toFixed(1)}%)`);
console.log(`缺失项目: ${this.results.summary.missing} (${((this.results.summary.missing / this.results.summary.total) * 100).toFixed(1)}%)`);
if (this.results.summary.missing > 0) {
console.log('\n⚠ 需要关注的缺失项:');
const missingItems = this.results.controllers.filter(item => !item.matched);
for (const item of missingItems.slice(0, 10)) { // 只显示前10个
console.log(` - ${item.php.type}/${item.php.module}/${item.php.name}.php`);
}
if (missingItems.length > 10) {
console.log(` ... 还有 ${missingItems.length - 10} 个缺失项`);
}
}
}
/**
* 运行完整检查
*/
async run() {
console.log('🚀 PHP与NestJS项目自动映射检查器');
console.log('='.repeat(50));
if (!this.checkDirectories()) {
process.exit(1);
}
try {
this.checkControllerMapping();
this.checkServiceMapping();
this.generateSummary();
console.log('\n✅ 检查完成!');
if (this.results.summary.missing > 0) {
console.log('\n💡 建议: 根据缺失项创建对应的NestJS文件');
process.exit(1);
}
} catch (error) {
console.error('❌ 检查过程中出现错误:', error.message);
process.exit(1);
}
}
}
// 运行检查器
if (require.main === module) {
const checker = new AutoMappingChecker();
checker.run().catch(console.error);
}
module.exports = AutoMappingChecker;