feat: 重构多语言模块,符合NestJS规范
- 重构LanguageUtils为LanguageService,实现ILanguageService接口 - 移除自定义验证管道和装饰器,使用标准NestJS验证 - 集成框架ValidatorService进行业务验证 - 简化目录结构,移除不必要的子目录 - 支持模块化语言包加载(common、user、order等) - 统一API响应格式(code、msg、data、timestamp) - 添加ValidationExceptionFilter处理多语言验证错误 - 完善多语言示例和文档
This commit is contained in:
455
tools/conversion-pipeline.js
Normal file
455
tools/conversion-pipeline.js
Normal file
@@ -0,0 +1,455 @@
|
||||
/**
|
||||
* 多阶段转换管道
|
||||
* 为AI自动生成打下基石
|
||||
*/
|
||||
|
||||
const ConversionRulesDatabase = require('./conversion-rules-database');
|
||||
|
||||
class ConversionPipeline {
|
||||
constructor() {
|
||||
this.rulesDB = new ConversionRulesDatabase();
|
||||
this.stages = [
|
||||
'preprocessing', // 预处理
|
||||
'syntax', // 语法转换
|
||||
'semantic', // 语义转换
|
||||
'context', // 上下文转换
|
||||
'validation', // 验证
|
||||
'postprocessing' // 后处理
|
||||
];
|
||||
|
||||
this.stageHandlers = {
|
||||
preprocessing: this.preprocess.bind(this),
|
||||
syntax: this.convertSyntax.bind(this),
|
||||
semantic: this.convertSemantic.bind(this),
|
||||
context: this.convertContext.bind(this),
|
||||
validation: this.validate.bind(this),
|
||||
postprocessing: this.postprocess.bind(this)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行完整转换管道
|
||||
*/
|
||||
async convert(phpCode, context = {}) {
|
||||
let convertedCode = phpCode;
|
||||
const results = {
|
||||
original: phpCode,
|
||||
stages: {},
|
||||
errors: [],
|
||||
warnings: [],
|
||||
metrics: {}
|
||||
};
|
||||
|
||||
console.log('🚀 开始多阶段转换管道...');
|
||||
|
||||
for (const stage of this.stages) {
|
||||
try {
|
||||
console.log(`📋 执行阶段: ${stage}`);
|
||||
const startTime = Date.now();
|
||||
|
||||
convertedCode = await this.stageHandlers[stage](convertedCode, context, results);
|
||||
|
||||
const endTime = Date.now();
|
||||
results.stages[stage] = {
|
||||
input: results.stages[stage - 1]?.output || phpCode,
|
||||
output: convertedCode,
|
||||
duration: endTime - startTime,
|
||||
success: true
|
||||
};
|
||||
|
||||
console.log(`✅ 阶段 ${stage} 完成 (${endTime - startTime}ms)`);
|
||||
} catch (error) {
|
||||
console.error(`❌ 阶段 ${stage} 失败:`, error.message);
|
||||
results.errors.push({
|
||||
stage,
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
results.stages[stage] = {
|
||||
success: false,
|
||||
error: error.message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
results.final = convertedCode;
|
||||
results.metrics = this.calculateMetrics(results);
|
||||
|
||||
console.log('🎉 转换管道完成!');
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* 预处理阶段
|
||||
*/
|
||||
async preprocess(code, context, results) {
|
||||
console.log(' 🔧 预处理: 清理和标准化代码...');
|
||||
|
||||
// 清理代码
|
||||
let processed = code
|
||||
// 移除多余的空白
|
||||
.replace(/\s+/g, ' ')
|
||||
.replace(/\n\s*\n/g, '\n')
|
||||
// 标准化换行
|
||||
.replace(/\r\n/g, '\n')
|
||||
.replace(/\r/g, '\n')
|
||||
// 移除注释中的特殊字符
|
||||
.replace(/\/\*[\s\S]*?\*\//g, (match) => {
|
||||
return match.replace(/[^\x20-\x7E\n]/g, '');
|
||||
});
|
||||
|
||||
// 检测代码特征
|
||||
const features = this.detectFeatures(processed);
|
||||
context.features = features;
|
||||
|
||||
console.log(` 📊 检测到特征: ${Object.keys(features).join(', ')}`);
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* 语法转换阶段
|
||||
*/
|
||||
async convertSyntax(code, context, results) {
|
||||
console.log(' 🔄 语法转换: 基础PHP到TypeScript转换...');
|
||||
|
||||
// 应用基础语法转换规则
|
||||
let converted = this.rulesDB.applyRules(code, 'syntax');
|
||||
|
||||
// 应用类型转换规则
|
||||
converted = this.rulesDB.applyRules(converted, 'types');
|
||||
|
||||
// 应用方法转换规则
|
||||
converted = this.rulesDB.applyRules(converted, 'methods');
|
||||
|
||||
// 应用数组和对象转换规则
|
||||
converted = this.rulesDB.applyRules(converted, 'collections');
|
||||
|
||||
// 应用异常处理转换规则
|
||||
converted = this.rulesDB.applyRules(converted, 'exceptions');
|
||||
|
||||
// 应用字符串处理规则
|
||||
converted = this.rulesDB.applyRules(converted, 'strings');
|
||||
|
||||
console.log(` 📈 语法转换完成,代码长度: ${converted.length}`);
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
/**
|
||||
* 语义转换阶段
|
||||
*/
|
||||
async convertSemantic(code, context, results) {
|
||||
console.log(' 🧠 语义转换: 业务逻辑语义转换...');
|
||||
|
||||
// 应用服务调用转换规则
|
||||
let converted = this.rulesDB.applyRules(code, 'services');
|
||||
|
||||
// 智能识别和转换业务逻辑模式
|
||||
converted = this.convertBusinessPatterns(converted, context);
|
||||
|
||||
// 转换控制流
|
||||
converted = this.convertControlFlow(converted, context);
|
||||
|
||||
console.log(` 🎯 语义转换完成,业务模式识别: ${context.features?.businessPatterns?.length || 0}个`);
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
/**
|
||||
* 上下文转换阶段
|
||||
*/
|
||||
async convertContext(code, context, results) {
|
||||
console.log(' 🎭 上下文转换: 根据代码上下文优化转换...');
|
||||
|
||||
let converted = code;
|
||||
|
||||
// 根据文件类型应用不同的转换策略
|
||||
if (context.fileType === 'service') {
|
||||
converted = this.convertServiceContext(converted, context);
|
||||
} else if (context.fileType === 'controller') {
|
||||
converted = this.convertControllerContext(converted, context);
|
||||
} else if (context.fileType === 'entity') {
|
||||
converted = this.convertEntityContext(converted, context);
|
||||
}
|
||||
|
||||
// 根据业务领域应用特定转换
|
||||
if (context.businessDomain) {
|
||||
converted = this.convertBusinessDomain(converted, context);
|
||||
}
|
||||
|
||||
console.log(` 🏗️ 上下文转换完成,文件类型: ${context.fileType || 'unknown'}`);
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证阶段
|
||||
*/
|
||||
async validate(code, context, results) {
|
||||
console.log(' ✅ 验证: 检查转换质量和语法正确性...');
|
||||
|
||||
const validation = {
|
||||
syntax: this.validateSyntax(code),
|
||||
types: this.validateTypes(code),
|
||||
imports: this.validateImports(code),
|
||||
business: this.validateBusinessLogic(code, context)
|
||||
};
|
||||
|
||||
// 收集验证结果
|
||||
const errors = [];
|
||||
const warnings = [];
|
||||
|
||||
Object.entries(validation).forEach(([type, result]) => {
|
||||
if (result.errors) {
|
||||
errors.push(...result.errors.map(e => ({ type, ...e })));
|
||||
}
|
||||
if (result.warnings) {
|
||||
warnings.push(...result.warnings.map(w => ({ type, ...w })));
|
||||
}
|
||||
});
|
||||
|
||||
results.errors.push(...errors);
|
||||
results.warnings.push(...warnings);
|
||||
|
||||
console.log(` 📊 验证完成: ${errors.length}个错误, ${warnings.length}个警告`);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* 后处理阶段
|
||||
*/
|
||||
async postprocess(code, context, results) {
|
||||
console.log(' 🎨 后处理: 最终优化和格式化...');
|
||||
|
||||
// 应用语法错误修复规则
|
||||
let processed = this.rulesDB.applyRules(code, 'syntaxFixes');
|
||||
|
||||
// 格式化代码
|
||||
processed = this.formatCode(processed);
|
||||
|
||||
// 添加必要的导入语句
|
||||
processed = this.addImports(processed, context);
|
||||
|
||||
console.log(` 🎉 后处理完成,最终代码长度: ${processed.length}`);
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测代码特征
|
||||
*/
|
||||
detectFeatures(code) {
|
||||
const features = {
|
||||
hasClasses: /class\s+\w+/.test(code),
|
||||
hasFunctions: /function\s+\w+/.test(code),
|
||||
hasArrays: /array\s*\(/.test(code),
|
||||
hasObjects: /->\s*\w+/.test(code),
|
||||
hasExceptions: /throw\s+new/.test(code),
|
||||
hasServices: /new\s+[A-Z]\w+Service/.test(code),
|
||||
hasControllers: /class\s+\w+Controller/.test(code),
|
||||
hasEntities: /@Entity|@Table/.test(code),
|
||||
businessPatterns: []
|
||||
};
|
||||
|
||||
// 检测业务模式
|
||||
const businessPatterns = [
|
||||
{ pattern: /success\s*\(/, name: 'success_response' },
|
||||
{ pattern: /error\s*\(/, name: 'error_response' },
|
||||
{ pattern: /validate\s*\(/, name: 'validation' },
|
||||
{ pattern: /cache\s*\(/, name: 'caching' },
|
||||
{ pattern: /log\s*\(/, name: 'logging' }
|
||||
];
|
||||
|
||||
businessPatterns.forEach(({ pattern, name }) => {
|
||||
if (pattern.test(code)) {
|
||||
features.businessPatterns.push(name);
|
||||
}
|
||||
});
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换业务模式
|
||||
*/
|
||||
convertBusinessPatterns(code, context) {
|
||||
let converted = code;
|
||||
|
||||
// 转换success响应
|
||||
converted = converted.replace(/return\s+success\s*\(([^)]+)\)/g, (match, data) => {
|
||||
return `return { success: true, data: ${data} };`;
|
||||
});
|
||||
|
||||
// 转换error响应
|
||||
converted = converted.replace(/return\s+error\s*\(([^)]+)\)/g, (match, message) => {
|
||||
return `throw new BusinessException(${message});`;
|
||||
});
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换控制流
|
||||
*/
|
||||
convertControlFlow(code, context) {
|
||||
let converted = code;
|
||||
|
||||
// 转换PHP控制流到TypeScript
|
||||
converted = converted.replace(/foreach\s*\(\s*([^)]+)\s+as\s+([^)]+)\s*\)/g, 'for (const $2 of $1)');
|
||||
converted = converted.replace(/foreach\s*\(\s*([^)]+)\s+as\s+([^)]+)\s*=>\s*([^)]+)\s*\)/g, 'for (const [$3, $2] of Object.entries($1))');
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务上下文转换
|
||||
*/
|
||||
convertServiceContext(code, context) {
|
||||
// 服务特定的转换逻辑
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* 控制器上下文转换
|
||||
*/
|
||||
convertControllerContext(code, context) {
|
||||
// 控制器特定的转换逻辑
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实体上下文转换
|
||||
*/
|
||||
convertEntityContext(code, context) {
|
||||
// 实体特定的转换逻辑
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务领域转换
|
||||
*/
|
||||
convertBusinessDomain(code, context) {
|
||||
// 根据业务领域应用特定转换
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证语法
|
||||
*/
|
||||
validateSyntax(code) {
|
||||
const errors = [];
|
||||
const warnings = [];
|
||||
|
||||
// 检查基本语法错误
|
||||
if (code.includes(']]')) {
|
||||
errors.push({ message: '发现方括号错误', line: this.findLineNumber(code, ']]') });
|
||||
}
|
||||
|
||||
if (code.includes('BusinessBusinessException')) {
|
||||
errors.push({ message: '发现重复的Business前缀', line: this.findLineNumber(code, 'BusinessBusinessException') });
|
||||
}
|
||||
|
||||
return { errors, warnings };
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证类型
|
||||
*/
|
||||
validateTypes(code) {
|
||||
const errors = [];
|
||||
const warnings = [];
|
||||
|
||||
// 类型验证逻辑
|
||||
return { errors, warnings };
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证导入
|
||||
*/
|
||||
validateImports(code) {
|
||||
const errors = [];
|
||||
const warnings = [];
|
||||
|
||||
// 导入验证逻辑
|
||||
return { errors, warnings };
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证业务逻辑
|
||||
*/
|
||||
validateBusinessLogic(code, context) {
|
||||
const errors = [];
|
||||
const warnings = [];
|
||||
|
||||
// 业务逻辑验证
|
||||
return { errors, warnings };
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化代码
|
||||
*/
|
||||
formatCode(code) {
|
||||
// 简单的代码格式化
|
||||
return code
|
||||
.replace(/\s+/g, ' ')
|
||||
.replace(/\n\s*\n/g, '\n')
|
||||
.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加导入语句
|
||||
*/
|
||||
addImports(code, context) {
|
||||
// 根据代码内容添加必要的导入
|
||||
let imports = [];
|
||||
|
||||
if (code.includes('BusinessException')) {
|
||||
imports.push("import { BusinessException } from '@wwjCommon/exceptions/business.exception';");
|
||||
}
|
||||
|
||||
if (code.includes('@Injectable')) {
|
||||
imports.push("import { Injectable } from '@nestjs/common';");
|
||||
}
|
||||
|
||||
if (imports.length > 0) {
|
||||
return imports.join('\n') + '\n\n' + code;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算指标
|
||||
*/
|
||||
calculateMetrics(results) {
|
||||
const originalLength = results.original.length;
|
||||
const finalLength = results.final.length;
|
||||
|
||||
return {
|
||||
originalLength,
|
||||
finalLength,
|
||||
compressionRatio: (originalLength - finalLength) / originalLength,
|
||||
errorCount: results.errors.length,
|
||||
warningCount: results.warnings.length,
|
||||
stageCount: Object.keys(results.stages).length,
|
||||
totalDuration: Object.values(results.stages).reduce((sum, stage) => sum + (stage.duration || 0), 0)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找行号
|
||||
*/
|
||||
findLineNumber(code, searchText) {
|
||||
const lines = code.split('\n');
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (lines[i].includes(searchText)) {
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ConversionPipeline;
|
||||
Reference in New Issue
Block a user