Skip to content

Better Swagger / OpenAPI types #857

Open
@caioquirino

Description

@caioquirino

Hello, good morning! Thanks for creating and maintaining such nice tool to ease our lifes with pagination! I am using it together with Swagger yaml generation and swagger-codegen in a Monorepo, so I can get type safety in the entire Full-Stack project.

When I use @nestjs/swagger with nestjs-typeorm-paginate, since it uses generics for the Pagination object, I had to manually annotate the Schema so it gets described properly in the swagger file.

I am wondering if we can either annotate the types in this project so it gets a more out-of-the-box swagger generation experience, or if the utility decorator can be part of it as well as some instructions in how to implement it properly :)

In any ways, here is the decorator that solved my problem:

import { Pagination } from 'nestjs-typeorm-paginate'
import { Type, applyDecorators } from "@nestjs/common"
import { ApiExtraModels, ApiOkResponse, getSchemaPath } from '@nestjs/swagger'

export const ApiOkResponsePaginated = <DataDto extends Type<unknown>>(dataDto: DataDto) =>
  applyDecorators(
    ApiExtraModels(Pagination, dataDto),
    ApiOkResponse({
      schema: {
        allOf: [
          { $ref: getSchemaPath(Pagination) },
          {
            properties: {
              items: {
                type: 'array',
                items: { $ref: getSchemaPath(dataDto) },
              },
              meta: {
                type: 'object',
                properties: {
                  'itemCount': {
                    type: 'number'
                  },
                  'totalItems': {
                    type: 'number'
                  },
                  'itemsPerPage': {
                    type: 'number'
                  },
                  'totalPages': {
                    type: 'number'
                  },
                  'currentPage': {
                    type: 'number'
                  }
                },
                required: ['itemCount', 'totalItems', 'itemsPerPage', 'totalPages', 'currentPage']
              },
              links: {
                type: 'object',
                properties: {
                  'first': {
                    type: 'string'
                  },
                  'previous': {
                    type: 'string'
                  },
                  'next': {
                    type: 'string'
                  },
                  'last': {
                    type: 'string'
                  }
                }
              }
            },
            required: ['items', 'meta']
          },
        ],
      },
    })
  )

And the way I have used is:

  @ApiQuery({ name: 'page', type: "number" })
  @ApiQuery({ name: 'limit', type: "number" })
  @ApiOkResponsePaginated(Cat)
  @Get()
  findAll(
    @Query('page', new DefaultValuePipe(1), ParseIntPipe) page = 1,
    @Query('limit', new DefaultValuePipe(10), ParseIntPipe) limit = 10,
  ): Promise<Pagination<Cat>> {
    limit = limit > 10 ? 10 : limit
    return this.catsService.findAll({ page, limit })
  }

Cheers!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions