Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

blog/nestjs-swagger-generics #12

Closed
utterances-bot opened this issue Apr 15, 2021 · 9 comments
Closed

blog/nestjs-swagger-generics #12

utterances-bot opened this issue Apr 15, 2021 · 9 comments

Comments

@utterances-bot
Copy link

How to generate Generics DTOs with nestjs/swagger | Chau Tran

nestjs/swagger provides consumers with enough tools to generate proper OpenAPI specs for Generics. Although, it is not straight-forward, yet it is possible.

https://nartc.me/blog/nestjs-swagger-generics

Copy link

Hey! Thanks a lot for that explanation, it really helped me!

Copy link

Not working for me

Copy link

hakimio commented May 21, 2021

Works great even with the latest version of nestJS (v7.6). Here is a full example which doesn't require putting @ApiExtraModels() on every controller (when using NestJS Swagger CLI Plugin):

import {ApiOkResponse, getSchemaPath} from '@nestjs/swagger';
import {applyDecorators, Type} from '@nestjs/common';

export class ListResponse<T> {
    count: number;
    next?: string;
    previous?: string;
    results: T[];
}

export const ApiListResponse = <TModel extends Type<unknown>>(model: TModel) => {
    return applyDecorators(
        ApiOkResponse({
            schema: {
                allOf: [
                    {
                        properties: {
                            count: {
                                type: 'number'
                            },
                            next: {
                                type: 'string',
                                nullable: true
                            },
                            previous: {
                                type: 'string',
                                nullable: true
                            },
                            results: {
                                type: 'array',
                                items: {$ref: getSchemaPath(model)}
                            }
                        }
                    }
                ]
            }
        })
    );
};

Copy link

@hakimio ListResponse is missing to generate the API.

Copy link

hakimio commented May 28, 2021

@markus2610 Not sure I understand what issue you are having. Can you show how you are using the decorator and what error you are getting?

Copy link

@hakimio No error, only the result model is generated without the wrapper class with count etc.

@hakimio
Copy link

hakimio commented May 28, 2021

@markus2610 Try the @ApiListResponse() decorator I have posted. It works as intended.

@hakimio
Copy link

hakimio commented May 28, 2021

Also, for those having issue with the original solution, remember to add @ApiExtraModels(PaginatedDto, UserDto) decorator to your controller class.

Copy link

Great article, and thanks for the code snippet @hakimio.

I also experienced an error like @markus2610 with the decorator code from @hakimio on a project running @nestjs/swagger": "^5.0.9" and "swagger-ui-express": "^4.1.6".

For example, a controller method returning a paginated list of User entities, decorated with ApiPaginatedResponse(User), displayed the following error message at the top of the Swagger UI: Could not resolve reference: #/components/schemas/User. The response value for my endpoint (which should also include a count property) was erroneously displayed as the following, and User should appear as an object not a string:

  "data": [
    "string"
  ]

My entities and DTO's are named per NestJS conventions as required by the default configuration of the nestjs cli plugin from @nestjs/swagger.

Other features implemented by the plugin seem to work.

To fix/workaround, I simply added ApiExtraModels(model) to the applyDecorators() args in @hakimio's decorator implementation. Hopefully that helps anyone who also wants to avoid having to remember to decorate their controller classes or methods with @ApiExtraModels().

An example of the fixed (expected) result:

{
  "count": 0,
  "data": [
    {
      "uuid": "string",
      "email": "string",
      "name": "string",
    }
  ]
}

Interestingly I didn't have add my generic Pagination DTO via ApiExtraModels(), only the entity class.

@nartc nartc transferred this issue from nartc/tnc-scully-comments Dec 26, 2021
Repository owner locked and limited conversation to collaborators Dec 26, 2021
@nartc nartc converted this issue into discussion #20 Dec 26, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants