OpenAPITools / OpenAPITools/openapi-generator

[BUG][nestjs] When I have `tags` in my `openapi` specification openapi cannot generate api client for it

Open
#17,413 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

I was confused why openapi-generate-cli is not generating client api for my categories endpoints in my nestjs app. Then I realized when I add even a simple @ApiTags (imported from @nestjs/swagger) and create openapi specification (via this command ts-node --project tsconfig.json --transpile-only -r tsconfig-paths/register src/utils/create-openapi-json.util.ts), it is not gonna generate client api for that controller.

openapi-generator version

7.1.0

OpenAPI declaration file content or url
{
    "openapi": "3.0.0",
    "paths": {
        "/": {
            "get": {
                "operationId": "AppController_getHello",
                "parameters": [],
                "responses": { "200": { "description": "" } }
            }
        },
        "/health": {
            "get": {
                "operationId": "AppController_getHealth",
                "parameters": [],
                "responses": { "200": { "description": "" } }
            }
        },
        "/talent": {
            "post": {
                "operationId": "TalentController_create",
                "parameters": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CreateTalentDto"
                            }
                        }
                    }
                },
                "responses": { "201": { "description": "" } }
            },
            "get": {
                "operationId": "TalentController_findAll",
                "parameters": [],
                "responses": { "200": { "description": "" } }
            }
        },
        "/talent/{id}": {
            "get": {
                "operationId": "TalentController_findOne",
                "parameters": [
                    {
                        "name": "id",
                        "required": true,
                        "in": "path",
                        "schema": { "type": "string" }
                    }
                ],
                "responses": { "200": { "description": "" } }
            },
            "patch": {
                "operationId": "TalentController_update",
                "parameters": [
                    {
                        "name": "id",
                        "required": true,
                        "in": "path",
                        "schema": { "type": "string" }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateTalentDto"
                            }
                        }
                    }
                },
                "responses": { "200": { "description": "" } }
            },
            "delete": {
                "operationId": "TalentController_remove",
                "parameters": [
                    {
                        "name": "id",
                        "required": true,
                        "in": "path",
                        "schema": { "type": "string" }
                    }
                ],
                "responses": { "200": { "description": "" } }
            }
        },
        "/categories": {
            "post": {
                "operationId": "CategoryController_create",
                "summary": "Create a new category",
                "parameters": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CreateCategoryDto"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Return created category's id",
                        "content": {
                            "application/json": {
                                "schema": { "type": "string" }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad request",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BadRequestException"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Internal server error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/InternalServerErrorException"
                                }
                            }
                        }
                    }
                },
                "tags": ["Categories"]
            },
            "get": {
                "operationId": "CategoryController_findAll",
                "summary": "Fetch categories",
                "parameters": [],
                "responses": {
                    "200": {
                        "description": "Return created category's id",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/GetCategoriesResponse"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad request",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/BadRequestException"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Internal server error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/InternalServerErrorException"
                                }
                            }
                        }
                    }
                },
                "tags": ["Categories"]
            }
        },
        "/categories/{id}": {
            "get": {
                "operationId": "CategoryController_findOne",
                "parameters": [
                    {
                        "name": "id",
                        "required": true,
                        "in": "path",
                        "schema": { "type": "string" }
                    }
                ],
                "responses": { "200": { "description": "" } },
                "tags": ["Categories"]
            },
            "patch": {
                "operationId": "CategoryController_update",
                "parameters": [
                    {
                        "name": "id",
                        "required": true,
                        "in": "path",
                        "schema": { "type": "string" }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/UpdateCategoryDto"
                            }
                        }
                    }
                },
                "responses": { "200": { "description": "" } },
                "tags": ["Categories"]
            },
            "delete": {
                "operationId": "CategoryController_remove",
                "parameters": [
                    {
                        "name": "id",
                        "required": true,
                        "in": "path",
                        "schema": { "type": "string" }
                    }
                ],
                "responses": { "200": { "description": "" } },
                "tags": ["Categories"]
            }
        }
    },
    "info": {
        "title": "My Typeorm RESTful API",
        "description": "It is just another test and has nothing to do with Typeorm API",
        "version": "1.0.0",
        "contact": {}
    },
    "tags": [],
    "servers": [{ "url": "http://localhost:3000" }],
    "components": {
        "schemas": {
            "CreateTalentDto": { "type": "object", "properties": {} },
            "UpdateTalentDto": { "type": "object", "properties": {} },
            "CreateCategoryDto": {
                "type": "object",
                "properties": {}
            },
            "BadRequestException": {
                "type": "object",
                "properties": {}
            },
            "InternalServerErrorException": {
                "type": "object",
                "properties": {}
            },
            "GetCategoriesResponse": {
                "type": "object",
                "properties": {}
            },
            "UpdateCategoryDto": {
                "type": "object",
                "properties": {}
            }
        }
    }
}
Generation Details
{
    "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
    "spaces": 2,
    "generator-cli": {
        "useDocker": true,
        "version": "7.1.0"
    }
}
Steps to reproduce
  1. Clone this repo: https://github.com/kasir-barati/nestjs-materials/
  2. Open the cloned repo in your IDE
  3. open integrated terminal
  4. cd typeorm
  5. pnpm i --frozen-lockfile
  6. pnpm openapi:create
  7. pnpm openapi:generate
  8. Open this file: typeorm/src/api-client/api.ts
  9. Now search for export class DefaultApi extends BaseAPI {
  10. As you can observe, none of the category endpoints are present. but talent endpoints are there.
  11. Now open typeorm/src/modules/talent/talent.controller.ts file and uncomment these two line:
    // import { ApiTags } from '@nestjs/swagger';
    // @ApiTags('Talents')
    
  12. repeat these steps: 6, 7, 8, and 9
  13. Now this time you cannot see any of the talent endpoint too.
Related issues/PRs

IDK if there is any, or at least I could not find them

Suggest a fix

TBH IDK what's the issue 😢

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the issue from the listed steps with pnpm openapi:create and pnpm openapi:generate in the typeorm project. Compare typeorm/src/api-client/api.ts with and without @ApiTags in typeorm/src/modules/talent/talent.controller.ts, using the supplied OpenAPI document to trace how tagged operations are handled. Done means category and talent endpoints are generated consistently when tags are present.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, openapi, typescript
Domain
api, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.