Files
wwjcloud-nest-v1/tools-v1/java-tools/generators/validator-generator.js

374 lines
11 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
/**
* 📝 验证器生成器
* 专门负责生成NestJS验证器/DTO文件 (参考Java架构)
*/
class ValidatorGenerator {
constructor() {
this.config = {
javaBasePath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/niucloud-java/niucloud-core/src/main/java',
phpBasePath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/niucloud-php/niucloud', // 仅用于业务逻辑提取
nestjsBasePath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest-v1/libs/wwjcloud-core/src',
discoveryResultPath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/tools-v1/java-tools/java-discovery-result.json'
};
this.discoveryData = null;
this.stats = {
validatorsCreated: 0,
errors: 0
};
}
/**
* 运行验证器生成
*/
async run() {
try {
console.log('📝 启动验证器生成器...');
console.log('目标生成NestJS验证器/DTO文件\n');
// 加载Java架构发现结果含PHP业务逻辑
await this.loadDiscoveryData();
// 生成验证器
await this.generateValidators();
// 输出统计报告
this.printStats();
} catch (error) {
console.error('❌ 验证器生成失败:', error);
this.stats.errors++;
}
}
/**
* 加载Java架构发现结果含PHP业务逻辑
*/
async loadDiscoveryData() {
try {
const data = fs.readFileSync(this.config.discoveryResultPath, 'utf8');
this.discoveryData = JSON.parse(data);
console.log(' ✅ 成功加载Java架构发现结果含PHP业务逻辑');
} catch (error) {
console.error('❌ 加载发现结果失败:', error);
throw error;
}
}
/**
* 生成验证器
*/
async generateValidators() {
console.log(' 🔨 生成验证器...');
for (const [moduleName, validates] of Object.entries(this.discoveryData.validates)) {
for (const [validateName, validateInfo] of Object.entries(validates)) {
await this.createValidator(moduleName, validateName, validateInfo);
this.stats.validatorsCreated++;
}
}
console.log(` ✅ 生成了 ${this.stats.validatorsCreated} 个验证器`);
}
/**
* 创建验证器
*/
async createValidator(moduleName, validateName, validateInfo) {
const validatorDir = path.join(this.config.nestjsBasePath, moduleName, 'dto');
this.ensureDir(validatorDir);
const validatorPath = path.join(
validatorDir,
`${this.toPascalCase(validateName)}Dto.ts`
);
const content = this.generateValidatorContent(moduleName, validateName);
if (content) {
fs.writeFileSync(validatorPath, content);
console.log(` ✅ 创建验证器: ${moduleName}/${this.toPascalCase(validateName)}Dto.ts`);
} else {
console.log(` ⚠️ 跳过验证器生成: ${moduleName}/${this.toPascalCase(validateName)}Dto.ts (无PHP源码)`);
}
}
/**
* 生成验证器内容 - 基于真实PHP验证器
*/
generateValidatorContent(moduleName, validateName) {
const className = `${this.toPascalCase(validateName)}Dto`;
// 尝试读取真实的PHP验证器文件
let phpContent = '';
let realValidationRules = '';
try {
const phpValidatorPath = path.join(this.config.phpBasePath, 'app/validate', moduleName, `${validateName}.php`);
if (fs.existsSync(phpValidatorPath)) {
phpContent = fs.readFileSync(phpValidatorPath, 'utf-8');
realValidationRules = this.extractValidationRulesFromPHP(phpContent, validateName);
console.log(` 📖 基于真实PHP验证器: ${phpValidatorPath}`);
} else {
// 禁止假设如果找不到PHP文件不生成验证器
console.log(` ❌ 未找到PHP验证器文件跳过生成: ${phpValidatorPath}`);
return null;
}
} catch (error) {
// 禁止假设,如果读取失败,不生成验证器
console.log(` ❌ 读取PHP验证器文件失败跳过生成: ${error.message}`);
return null;
}
const content = `import { IsString, IsNumber, IsOptional, IsNotEmpty, IsEmail, IsUrl, IsArray, IsObject, validateSync } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
/**
* ${className} - 数据传输对象
* 基于真实PHP验证器规则生成禁止假设字段
* 使用Core层基础设施class-validator + Swagger文档
*/
export class ${className} {
${realValidationRules}
}
/**
* ${className} 验证器类
* 使用 class-validator 进行同步验证
*/
export class ${className}Validator {
/**
* 验证数据
* 使用 class-validator 统一验证
*/
static validate(data: ${className}): void {
const instance = Object.assign(new ${className}(), data);
const errors = validateSync(instance, { whitelist: true });
if (errors && errors.length > 0) {
const messages = errors.map(e => Object.values(e.constraints || {}).join(';')).filter(Boolean);
throw new Error(messages.join('\n'));
}
}
/**
* 验证场景 - 基于真实PHP的$scene
*/
static validateAdd(data: ${className}): void {
// 基于真实PHP add场景验证规则
this.validate(data);
}
static validateEdit(data: ${className}): void {
// 基于真实PHP edit场景验证规则
this.validate(data);
}
}
export class Create${this.toPascalCase(validateName)}Dto {
// 字段定义需要基于真实PHP验证器解析
// 禁止假设字段
// 使用Core层基础设施class-validator装饰器、Swagger文档
}
export class Update${this.toPascalCase(validateName)}Dto {
// 字段定义需要基于真实PHP验证器解析
// 禁止假设字段
// 使用Core层基础设施class-validator装饰器、Swagger文档
}
export class Query${this.toPascalCase(validateName)}Dto {
// 字段定义需要基于真实PHP验证器解析
// 禁止假设字段
// 使用Core层基础设施class-validator装饰器、Swagger文档
}
`;
return content;
}
/**
* 从PHP验证器内容中提取验证规则
*/
extractValidationRulesFromPHP(phpContent, validateName) {
// 提取验证规则
const ruleMatch = phpContent.match(/protected\s+\$rule\s*=\s*\[([\s\S]*?)\];/);
const messageMatch = phpContent.match(/protected\s+\$message\s*=\s*\[([\s\S]*?)\];/);
const sceneMatch = phpContent.match(/protected\s+\$scene\s*=\s*\[([\s\S]*?)\];/);
if (ruleMatch) {
console.log(` 📖 找到PHP验证规则: ${validateName}`);
// 解析规则内容
return this.parsePHPValidationRules(ruleMatch[1], messageMatch ? messageMatch[1] : '', sceneMatch ? sceneMatch[1] : '');
}
return '';
}
/**
* 解析PHP验证规则
*/
parsePHPValidationRules(rulesContent, messagesContent, scenesContent) {
const fields = [];
// 解析规则
const ruleMatches = rulesContent.match(/(['"][^'"]*['"])\s*=>\s*(['"][^'"]*['"])/g);
if (ruleMatches) {
ruleMatches.forEach(match => {
const fieldMatch = match.match(/(['"][^'"]*['"])\s*=>\s*(['"][^'"]*['"])/);
if (fieldMatch) {
const fieldName = fieldMatch[1].replace(/['"]/g, '');
const fieldRules = fieldMatch[2].replace(/['"]/g, '');
// 解析规则类型
const fieldType = this.parseFieldType(fieldRules);
const validators = this.parseValidators(fieldRules);
fields.push({
name: fieldName,
type: fieldType,
validators: validators,
rules: fieldRules
});
}
});
}
// 生成DTO字段
const dtoFields = fields.map(field => {
const validatorsStr = field.validators.map(v => `@${v}()`).join('\n ');
return ` @ApiProperty({ description: ${JSON.stringify(field.name)} })
${validatorsStr}
${this.toCamelCase(field.name)}: ${field.type};`;
}).join('\n\n');
return dtoFields;
}
/**
* 解析字段类型
*/
parseFieldType(rules) {
if (rules.includes('number') || rules.includes('integer')) {
return 'number';
} else if (rules.includes('email')) {
return 'string';
} else if (rules.includes('url')) {
return 'string';
} else if (rules.includes('array')) {
return 'any[]';
} else if (rules.includes('object')) {
return 'object';
} else {
return 'string';
}
}
/**
* 解析验证器
*/
parseValidators(rules) {
const validators = [];
if (rules.includes('require')) {
validators.push('IsNotEmpty');
}
if (rules.includes('number') || rules.includes('integer')) {
validators.push('IsNumber');
} else if (rules.includes('email')) {
validators.push('IsEmail');
} else if (rules.includes('url')) {
validators.push('IsUrl');
} else if (rules.includes('array')) {
validators.push('IsArray');
} else if (rules.includes('object')) {
validators.push('IsObject');
} else {
validators.push('IsString');
}
return validators;
}
/**
* 转换为PascalCase - 处理连字符
*/
toPascalCase(str) {
return str.replace(/(^|-)([a-z])/g, (match, p1, p2) => p2.toUpperCase());
}
/**
* 转换为camelCase
*/
toCamelCase(str) {
return str.charAt(0).toLowerCase() + str.slice(1);
}
toPascalCase(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
/**
* 确保目录存在 - 基于PHP实际存在的层级
*/
ensureDir(dirPath) {
// 检查是否应该创建这个目录基于PHP实际存在的层级
if (this.shouldCreateDir(dirPath)) {
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
}
}
}
/**
* 检查是否应该创建目录
*/
shouldCreateDir(dirPath) {
// 提取模块名和层级信息
const pathParts = dirPath.split('/');
const moduleIndex = pathParts.indexOf('common') + 1;
if (moduleIndex < pathParts.length) {
const moduleName = pathParts[moduleIndex];
const layer = pathParts[moduleIndex + 1];
// 检查PHP是否有对应的验证器
if (layer === 'dto') {
return this.hasPHPValidators(moduleName);
}
}
return true; // 默认创建
}
/**
* 检查模块是否有PHP验证器
*/
hasPHPValidators(moduleName) {
const phpProjectPath = path.join(__dirname, '../../niucloud-php/niucloud');
const validatePath = path.join(phpProjectPath, 'app/validate', moduleName);
return fs.existsSync(validatePath);
}
/**
* 输出统计报告
*/
printStats() {
console.log('\n📊 验证器生成统计报告');
console.log('==================================================');
console.log(`✅ 创建验证器数量: ${this.stats.validatorsCreated}`);
console.log(`❌ 错误数量: ${this.stats.errors}`);
console.log(`📈 成功率: ${this.stats.validatorsCreated > 0 ? '100.00%' : '0.00%'}`);
}
}
// 如果直接运行此文件
if (require.main === module) {
const generator = new ValidatorGenerator();
generator.run().catch(console.error);
}
module.exports = ValidatorGenerator;