添加ts从vo自动转换到dto
This commit is contained in:
parent
d69bdfea12
commit
e88210a9bc
229
typescripts/ts-transform-pojo.ts
Normal file
229
typescripts/ts-transform-pojo.ts
Normal file
@ -0,0 +1,229 @@
|
||||
import Schema, { Rules } from 'async-validator';
|
||||
|
||||
// 定义字段元数据接口
|
||||
interface FieldMetadata {
|
||||
type: 'string' | 'number' | 'boolean' | 'object' | 'array';
|
||||
voField?: string;
|
||||
rules?: Rules;
|
||||
nestedSchema?: SchemaBuilder<any>;
|
||||
}
|
||||
|
||||
// 链式API构建器类
|
||||
class SchemaBuilder<T> {
|
||||
private fields: Record<string, FieldMetadata> = {};
|
||||
private currentField: string | null = null;
|
||||
private currentMetadata: FieldMetadata | null = null;
|
||||
|
||||
constructor(private name: string) {}
|
||||
|
||||
// 添加字段
|
||||
field<K extends string>(name: K): SchemaBuilder<T & { [P in K]: any }> {
|
||||
this.currentField = name;
|
||||
this.currentMetadata = { type: 'string' };
|
||||
return this as unknown as SchemaBuilder<T & { [P in K]: any }>;
|
||||
}
|
||||
|
||||
// 设置字段类型
|
||||
type(type: FieldMetadata['type']): this {
|
||||
if (this.currentMetadata) {
|
||||
this.currentMetadata.type = type;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// 设置VO字段映射
|
||||
voField(name: string): this {
|
||||
if (this.currentMetadata) {
|
||||
this.currentMetadata.voField = name;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// 添加验证规则
|
||||
validate(rules: Rules): this {
|
||||
if (this.currentMetadata) {
|
||||
this.currentMetadata.rules = rules;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// 设置嵌套Schema
|
||||
nested(schema: SchemaBuilder<any>): this {
|
||||
if (this.currentMetadata) {
|
||||
this.currentMetadata.nestedSchema = schema;
|
||||
this.currentMetadata.type = 'object';
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// 完成字段定义
|
||||
end(): this {
|
||||
if (this.currentField && this.currentMetadata) {
|
||||
this.fields[this.currentField] = this.currentMetadata;
|
||||
this.currentField = null;
|
||||
this.currentMetadata = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// 生成TypeScript类型
|
||||
getType(): T {
|
||||
return {} as T;
|
||||
}
|
||||
|
||||
// 生成验证规则
|
||||
getValidationRules(): Rules {
|
||||
const rules: Rules = {};
|
||||
|
||||
for (const [field, metadata] of Object.entries(this.fields)) {
|
||||
if (metadata.rules) {
|
||||
rules[field] = metadata.rules;
|
||||
}
|
||||
|
||||
// 处理嵌套对象
|
||||
if (metadata.nestedSchema) {
|
||||
rules[field] = { ...rules[field], fields: metadata.nestedSchema.getValidationRules() };
|
||||
}
|
||||
}
|
||||
|
||||
return rules;
|
||||
}
|
||||
|
||||
// 获取字段元数据
|
||||
getFieldsMetadata(): Record<string, FieldMetadata> {
|
||||
return { ...this.fields };
|
||||
}
|
||||
}
|
||||
|
||||
// 创建Schema构建器的工厂函数
|
||||
function createSchema<T = {}>(name: string): SchemaBuilder<T> {
|
||||
return new SchemaBuilder<T>(name);
|
||||
}
|
||||
|
||||
// 从Schema提取TypeScript类型的工具类型
|
||||
type ExtractTypeFromSchema<T> = T extends SchemaBuilder<infer U> ? U : never;
|
||||
|
||||
// 生成验证规则
|
||||
function createRules<T>(schema: SchemaBuilder<T>): Rules {
|
||||
return schema.getValidationRules();
|
||||
}
|
||||
|
||||
// VO到DTO的转换函数
|
||||
function transformVoToDto<T>(data: any, schema: SchemaBuilder<T>): T {
|
||||
const fields = schema.getFieldsMetadata();
|
||||
const result: any = {};
|
||||
|
||||
for (const [dtoField, metadata] of Object.entries(fields)) {
|
||||
const voField = metadata.voField || dtoField;
|
||||
const value = data[voField];
|
||||
|
||||
// 处理嵌套对象
|
||||
if (metadata.nestedSchema && typeof value === 'object' && value !== null) {
|
||||
result[dtoField] = transformVoToDto(value, metadata.nestedSchema);
|
||||
} else {
|
||||
// 根据类型转换值
|
||||
switch (metadata.type) {
|
||||
case 'number':
|
||||
result[dtoField] = Number(value);
|
||||
break;
|
||||
case 'boolean':
|
||||
result[dtoField] = Boolean(value);
|
||||
break;
|
||||
default:
|
||||
result[dtoField] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result as T;
|
||||
}
|
||||
|
||||
// 带转换功能的API请求函数
|
||||
async function get<T>(url: string, schema: SchemaBuilder<T>): Promise<T> {
|
||||
// 模拟API请求
|
||||
const response = await fetch(url);
|
||||
const voData = await response.json();
|
||||
|
||||
// 转换VO到DTO
|
||||
const dtoData = transformVoToDto(voData, schema);
|
||||
|
||||
// 验证数据
|
||||
const validator = new Schema(schema.getValidationRules());
|
||||
try {
|
||||
await validator.validate(dtoData);
|
||||
} catch (errors) {
|
||||
// 确保验证错误被正确抛出
|
||||
throw new Error(`Validation failed: ${JSON.stringify(errors)}`);
|
||||
}
|
||||
|
||||
return dtoData;
|
||||
}
|
||||
|
||||
// Fix the export statement to ensure proper ESM exports
|
||||
export { createSchema, createRules, get, transformVoToDto, ExtractTypeFromSchema };
|
||||
|
||||
// 创建地址Schema
|
||||
const AddressSchema = createSchema('Address')
|
||||
.field('street')
|
||||
.type('string')
|
||||
.voField('streetName')
|
||||
.validate({ required: true, min: 2, max: 100 })
|
||||
.end()
|
||||
.field('city')
|
||||
.type('string')
|
||||
.validate({ required: true })
|
||||
.end()
|
||||
.field('zipCode')
|
||||
.type('string')
|
||||
.voField('postalCode')
|
||||
.validate({ required: true, pattern: /^\d{5}$/ })
|
||||
.end();
|
||||
|
||||
// 创建用户Schema
|
||||
const UserSchema = createSchema('User')
|
||||
.field('id')
|
||||
.type('number')
|
||||
.voField('userId')
|
||||
.validate({ required: true, type: 'number' })
|
||||
.end()
|
||||
.field('name')
|
||||
.type('string')
|
||||
.validate({ required: true, min: 2, max: 50 })
|
||||
.end()
|
||||
.field('email')
|
||||
.type('string')
|
||||
.validate({
|
||||
required: true,
|
||||
type: 'string',
|
||||
pattern: /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/,
|
||||
})
|
||||
.end()
|
||||
.field('age')
|
||||
.type('number')
|
||||
.validate({ type: 'number', min: 0, max: 150 })
|
||||
.end()
|
||||
.field('address')
|
||||
.type('object')
|
||||
.nested(AddressSchema)
|
||||
.validate({ type: 'object' })
|
||||
.end();
|
||||
|
||||
// 提取用户类型
|
||||
type User = ExtractTypeFromSchema<typeof UserSchema>;
|
||||
|
||||
// 获取验证规则
|
||||
const userRules = createRules(UserSchema);
|
||||
|
||||
// 使用示例
|
||||
async function fetchUser() {
|
||||
try {
|
||||
const user = await get<User>('/api/user/1', UserSchema);
|
||||
console.log('用户数据:', user);
|
||||
return user;
|
||||
} catch (error) {
|
||||
console.error('获取用户失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 执行示例
|
||||
fetchUser();
|
Loading…
x
Reference in New Issue
Block a user