Home > Blockchain >  Custom param decorator with Swagger documentation
Custom param decorator with Swagger documentation

Time:07-09

In Nestjs you can use @Query() query: MyDto to automatically validate your query params, and to generate a Swagger documentation.

I've created a custom decorator, that kinda replaces the @Query decorator. My custom decorator does a few things differently.

BUT, I can't find a way to generate the Swagger documentation automatically, for example:

Using @Query: Swagger screenshot with param documented

Controller:

@Get()
  findAll(@Query() query: AqpDto, @Tenant() tenantId: string) {
    return this.logsService.findAll(query, tenantId);
  }

Using my decorator: Swagger screenshot without params

@Get()
  findAll(@Aqp() query: AqpDto, @Tenant() tenantId: string) {
    return this.logsService.findAll(query, tenantId);
  }

I consume these APIs using swagger-client so the lack of the query param definitions is not only missing documentation, but also breaks the API call, as swagger-client doesn't send the params as expected.

I've tried applyDecorators, I tried to find ways to automatically execute the Query once my decorator is called, I tried to find the source code of Query to identify how it adds the Dto params to Swagger. I don't know what else to do do.

I'm trying to find a clean solution, but no luck so far. Any help is appreciated.

CodePudding user response:

The Query() related code can be found in the @nestjs/common package, in the route-params.decorator.ts file.

https://github.com/nestjs/nest/blob/master/packages/common/decorators/http/route-params.decorator.ts#L411

It doesn't do anything with Swagger, and it shouldn't, that's not its responsibility.

export function Query(
  property?: string | (Type<PipeTransform> | PipeTransform),
  ...pipes: (Type<PipeTransform> | PipeTransform)[]
): ParameterDecorator {
  return createPipesRouteParamDecorator(RouteParamtypes.QUERY)(
    property,
    ...pipes,
  );
}

The @Body(), @Query(), @Param()...etc. decorators all have a very similar implementation. They all call the createPipesRouteParamDecorator(...) function with a RouteParamtypes value.

export enum RouteParamtypes {
  BODY,
  QUERY,
  PARAM,
  ...
}

https://github.com/nestjs/nest/blob/master/packages/common/enums/route-paramtypes.enum.ts

In the end it uses Reflect.defineMetadata(...) to set metadata on the controller about the query, body, param...etc.

The @nestjs/swagger packages uses the constants under which this metadata is saved and gathers this metadata (using Reflect.getMetadata()).

For example:

https://github.com/nestjs/swagger/blob/master/lib/services/parameter-metadata-accessor.ts

Based on the gathered metadata its able to construct the Swagger documentation. You can tweak this by adding extra decorators provided by the @nestjs/swagger package. With these you can provide extra metadata that is gathered to help generate the Swagger documenation. In your case you can use the @ApiQuery() decorator to provide extra hints.

@ApiQuery({ 
  name: 'query', 
  schema: { .... },
  type: AqpDto,
  required: true
})
@Get()
findAll(@Aqp() query: AqpDto, @Tenant() tenantId: string) {
  ...
}
  • Related