Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better Swagger / OpenAPI types #857

Open
caioquirino opened this issue Sep 19, 2023 · 2 comments
Open

Better Swagger / OpenAPI types #857

caioquirino opened this issue Sep 19, 2023 · 2 comments

Comments

@caioquirino
Copy link

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!

@scayze
Copy link

scayze commented Jul 31, 2024

+1, that would be very lovely

@bashleigh
Copy link
Collaborator

That looks like a perfect solution! Would you like to create a PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants