【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. 返回转换后的数据

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

相关推荐
死神6545 小时前
Vibe Coding 实战:我用 Nuxt 3+NestJS 做了一个电商运营 SaaS
saas·nestjs·nuxt.js·电商运营·vibe coding
copyer_xyf2 天前
PostgreSQL 做向量检索:一条单库路线
数据库·agent·nestjs
Revolution612 天前
Nest.js 是什么:怎样用它写出第一个后端接口
后端·node.js·nestjs
濮水大叔4 天前
NestJS 与 CabloyJS 的 env/config 架构对比:从环境变量到实例级配置
前端·node.js·nestjs
Allshadow9 天前
Nest.js - 连接数据库
javascript·nestjs
Allshadow12 天前
Nest.js - 目录结构
javascript·nestjs
南一Nanyi13 天前
依赖注入和控制反转
前端·设计模式·nestjs
晓得迷路了14 天前
栗子前端技术周刊第 138 期 - NestJS 12、Astro 7.1、npm 12...
前端·javascript·nestjs
xiaofeichaichai16 天前
NestJS 实战:JWT 登录认证、Token 刷新与安全退出
redis·nestjs·jwt·twitter
无双_Joney18 天前
[四期 - 4] NestJS专栏 - 征召一下大家的意见,非常想知道大家都想看看Nest的哪些方面
前端·后端·nestjs