Response format with pagination and Swagger

See original GitHub issue

Hi everyone,

I’m recently run into the issue with Swagger response models and different response formats that @nestjsx/crud produces depending on the pagination options. By default, getManyBase returns data using this schema: Entity[], when offset and per_page are set: GetManyDefaultResponse<T>.

But for Swagger metadata only the 1st format is used. This might cause issues when API client is generated from metadata using tools like swagger-api/swagger-codegen.

As far as I know, it’s possible to set an alternative response model in OpenAPI 3 but this feature isn’t supported by @nestjs/swagger yet: https://github.com/nestjs/swagger/issues/43.

That would be nice to have all responses in the same format: GetManyDefaultResponse<T> or Entity[] (with meta in HTTP headers, for example X-Total-Count).

As a workaround, I’m overriding response metadata using ApiOkResponse decorator + an interceptor to transform responses.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:7 (6 by maintainers)

github_iconTop GitHub Comments

13reactions
michaelyalicommented, Jul 18, 2019

Ok, guys. I think one response format would be the best way. Will add it to the next release.

6reactions
roland-chernovcommented, Jul 17, 2019

@DaVarga Another part of the workaround (in addition to the interceptor) is Swagger meta overriding (possible after #113).

  1. Define generic class for the response model (similar to GetManyDefaultResponse interface but with optional props):
    class GetManyResponse<Entity> {
      @ApiModelProperty({ type: Object, isArray: true }) // will be overwritten
      public data: Entity[];
    
      @ApiModelPropertyOptional()
      public count?: number;
    // ...
    
  2. Define a factory function:
    type Entity = Function;
    
    function getManyResponseFor(type: Entity): typeof GetManyResponse {
      class GetManyResponseForEntity<Entity> extends GetManyResponse<Entity> {
        @ApiModelProperty({ type, isArray: true })
        public data: Entity[];
      }
      Object.defineProperty(GetManyResponseForEntity, 'name', {
        value: `GetManyResponseFor${type.name}`,
      });
    
      return GetManyResponseForEntity;
    }
    
  3. Add ApiOkResponse decorator to options:
    @Crud({
      model: {
        type: Company,
      },
      routes: {
        getManyBase: {
          interceptors: [GetManyResponseInterceptor],
          decorators: [
            ApiOkResponse({ type: getManyResponseFor(Company) }),
    // ...
    

Or as an alternative, simply pass total count as X-Total-Count header in an interceptor. Then no need to redefine Swagger meta.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to add generic pagination to swagger
In this article you'll learn how to design and implement a reusable swagger pagination solution to any RESTful API.
Read more >
Implementing pagination in Swagger definition for REST APIs
The response should include total records and the no. of records currently displayed. Here is an example - /orders: get: tags: - orders ......
Read more >
18 Scaling collection endpoints with filters and pagination
Pagination divides the collection into chunks. Any API call returns only the first chunk in the response.
Read more >
Pagination - The REST API basics
#Pagination. The vast majority of the responses containing a collection of resources will be paginated. Take a look at our reference to find...
Read more >
Links - Swagger
Another example is pagination via cursors, where the response includes a cursor to retrieve the next data set: GET /items?limit=100 ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found