Files
wwjcloud-nest-v1/tools/conversion-pipeline.js
wanwu b1e16be25d feat: 重构多语言模块,符合NestJS规范
- 重构LanguageUtils为LanguageService,实现ILanguageService接口
- 移除自定义验证管道和装饰器,使用标准NestJS验证
- 集成框架ValidatorService进行业务验证
- 简化目录结构,移除不必要的子目录
- 支持模块化语言包加载(common、user、order等)
- 统一API响应格式(code、msg、data、timestamp)
- 添加ValidationExceptionFilter处理多语言验证错误
- 完善多语言示例和文档
2025-10-06 10:56:59 +08:00

456 lines
12 KiB
JavaScript

/**
* 多阶段转换管道
* 为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;