nestjsx / nestjs-typeorm-paginate

:page_with_curl: Pagination response object function + types for typeorm + nestjs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Better Swagger / OpenAPI types

caioquirino opened this issue · comments

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!