【nest系列】之 VO 的配置

前提摘要:

nest 有提供单独的方法可供 vo 对象转换,但下面我是写了一个 crud 基类,由于不同子类的 vo 不同,需要对其进行配置才有下面这种设计思路

实现流程

markdown 复制代码
【实现流程分析】
1. 数据流转过程
   CRUD装饰器 -> 配置元数据 -> Transform装饰器 -> 拦截器处理 -> 最终输出

2. 核心组件关系
   - CRUD装饰器:配置中心,管理VO映射关系
   - Transform装饰器:元数据存储,提供转换信息
   - Transform拦截器:执行转换,处理响应数据

流程分析

1. 装饰器实现-VO配置收集

swift 复制代码
interface CurdOptions {
// ... 其他配置
  vos?: {
    findOne?: Type<any>
    findAll?: Type<any>
    findPage?: Type<any>
    create?: Type<any>
    update?: Type<any>
  }
}

2. 元数据处理

javascript 复制代码
export const Crud = (options: CurdOptions) => <T extends CrudController>(Target: Type<T>) => {
  // 1. 保存CRUD配置到元数据
  Reflect.defineMetadata(CRUD_OPTIONS, options, Target);
  // 2. 获取配置信息
  const { enabled, vos } = Reflect.getMetadata(CRUD_OPTIONS, Target) as CurdOptions;
  // 3. 构建方法映射表
  if (vos) {
    const methodMap = {};
    for (const value of enabled) {
      const { name } = typeof value === 'string' ? { name: value } : value;
      if (vos[name]) {
        // 为每个启用的方法配置VO转换
        methodMap[name] = {
          VoType: vos[name],
          options: {
            excludeExtraneousValues: true,
            enableImplicitConversion: true
          }
        };
      }
    }
    // 4. 应用Transform装饰器
    if (Object.keys(methodMap).length > 0) {
      TransformMethodMap(methodMap)(Target);
    }
  }
}

3. Transform装饰器与元数据

3.1. 元数据存储机制

typescript 复制代码
// transform.decorator.ts
export const TRANSFORM_METHOD_MAP_KEY = 'transformMethodMap';

// 方法映射装饰器
export const TransformMethodMap = (methodMap: Record<string, any>) => {
  return SetMetadata(TRANSFORM_METHOD_MAP_KEY, methodMap);
}

3.2. 元数据结构示例

yaml 复制代码
{
  'findOne': {
    VoType: UserDetailVo,
    options: {
      excludeExtraneousValues: true,
      enableImplicitConversion: true
    }
  },
  'findAll': {
    VoType: UserListVo,
    options: {
      excludeExtraneousValues: true,
      enableImplicitConversion: true
    }
  }
}

4. 拦截器处理流程

4.1. 数据拦截与转换

kotlin 复制代码
@Injectable()
export class TransformInterceptor implements NestInterceptor {
  constructor(private reflector: Reflector) { }
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      map(data => {
        // 1. 获取当前执行上下文
        const handler = context.getHandler();
        const cls = context.getClass();
        // 2. 获取方法映射表
        const methodMap = this.reflector.get(TRANSFORM_METHOD_MAP_KEY, cls) || {};
        const methodName = handler.name;
        const config = methodMap[methodName];
        if (!config) return data;
        // 3. 获取转换配置
        const { VoType, options } = config;
        // 4. 执行数据转换
        return this.transformData(data, VoType, options);
      })
    );
  }
  // 5. 根据数据类型处理不同的转换场景
  private transformData(data: any, VoType: any, options: TransformOptions) {
    // 处理分页数据
    if (data?.list && Array.isArray(data.list)) {
      return this.handlePaginatedData(data, VoType, options);
    }
    // 处理数组数据
    if (Array.isArray(data)) {
      return this.handleArrayData(data, VoType, options);
    }
    // 处理单个对象
    return this.handleSingleData(data, VoType, options);
  }
}

4.2. 协作流程示例

  1. 控制器定义
scala 复制代码
@Crud({
  enabled: ['findOne', 'findAll', 'findPage'],
  vos: {
    findOne: UserDetailVo,
    findAll: UserListVo,
    findPage: UserPageVo
  }
})
export class UsersController extends CrudController {
  // 控制器方法
}
  1. 执行流程
    1. CRUD 装饰器初始化
      1. 收集 VO 配置
      2. 创建方法映射表
      3. 通过 TransformMethodMap 存储元数据
    1. 请求处理
      1. 方法执行,返回原数据
    1. 拦截器处理
      1. 获取当前方法的 VO 配置
      2. 根据数据类型选择转换策略
      3. 执行数据转换
      4. 返回转换后的数据

有不足的地方请多多指教!!!

相关推荐
前端付豪4 小时前
Nest 项目小实践之图书增删改查
前端·node.js·nestjs
前端付豪2 天前
Nest 项目小实践之图书展示和搜索
前端·node.js·nestjs
前端付豪3 天前
Nest 项目小实践之前端注册登陆
前端·node.js·nestjs
Mr_li6 天前
NestJS 集成 TypeORM 的最优解
node.js·nestjs
前端付豪7 天前
Nest 项目小实践之注册登陆
前端·node.js·nestjs
Mr_li7 天前
手摸手,教你如何优雅的书写 NestJS 服务配置
node.js·nestjs
Jiude8 天前
AI 全栈时代的工程化护栏:Vben-Nest 让 Mock 契约落地成真实后端
前端·后端·nestjs
折七9 天前
NestJS 用了两年,我换了这个
typescript·node.js·nestjs
NEXT0616 天前
深度解析 JWT:从 RFC 原理到 NestJS 实战与架构权衡
前端·typescript·nestjs
明月_清风18 天前
从“搬运工”到“指挥官”:通过 IoC 容器重塑你的后端思维
后端·nestjs