1

背景:

我使用nestjs拦截器将控制器返回的数据放入data属性中并添加一些其他属性。现在我想用@ApiOkResponse它来反映嵌套的属性。

控制器返回

{
   prop1: 'val1',
   prop2:  'val2'
}

被拦截后返回

data: {
   prop1: 'val1',
   prop2:  'val2'
},
addedProp: 'addedVal'

我也说了两个类:

// Have many variations of similar classes (for different controllers (types of data)
class NotYetIntercepted {
   @ApiProperty()
   prop1: string;

   @ApiProperty()
   prop2: string;
}

class Intercepted<T = any> {
   @ApiProperty()
   data: T;

   @ApiProperty()
   addedProp: string;
}

挑战

现在我想添加到我的控制器@ApiOkResponse({ type: Intercepted })中,但还要以某种方式指定dataclass 的属性Intercepted应该是 type NotYetIntercepted

我尝试创建一个这样的自定义装饰器:

import { ValidateNested } from 'class-validator';
import { ApiProperty, ApiResponseOptions, ApiOkResponse } from '@nestjs/swagger';
import { Intercepted } from '@appnamespace/models';
import { Type } from 'class-transformer';

export const CustomApiOkResponse = (notYetIntercepted: Function, options?: Omit<ApiResponseOptions, 'type'>) => {

  class InterceptedWithData extends Intercepted {

    @ApiProperty()
    @ValidateNested()
    @Type(() => notYetIntercepted)
    data: typeof notYetIntercepted;
  }

  return ApiOkResponse({
    ...options,
    type: InterceptedWithData,
  });
};

那没有用。当我删除@Type() => notYetIntercepted)并设置它datadata: notYetIntercepted某种方式工作时(带有打字稿警告),但它将我swagger docs中的所有值覆盖为最后传递给(@CustomApiOkResponse(AnotherNotYetIntercepted))的值。

我知道我可以为每个嵌套数据类型创建一个类,但是有没有更简洁的解决方案?

感谢您的时间

4

1 回答 1

0

一种选择是使用自定义装饰器动态传递 Swagger 模式。在 nestjs/terminus 中已经完成了一些非常相似的事情 - 请参阅health-check.decorator.tshealth-check.schema.ts.

简而言之,您可以通过schema选项传递自定义定义。

export const CustomApiOkResponse = (notYetIntercepted: Function, options?: Omit<ApiResponseOptions, 'type'>) => {
  return ApiOkResponse({
    ...options,
    schema: {
     // .. your Swagger Schema
    }
  });
};
于 2020-04-12T18:29:53.187 回答