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

Generated JSON missing schemas #1123

Closed
willin opened this issue Jan 7, 2021 · 10 comments
Closed

Generated JSON missing schemas #1123

willin opened this issue Jan 7, 2021 · 10 comments

Comments

@willin
Copy link

willin commented Jan 7, 2021

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

QQ20210107-112510

json file:

{
  "openapi": "3.0.0",
  "info": {
    "title": "Cats example",
    "description": "The cats API description",
    "version": "1.0",
    "contact": {}
  },
  "tags": [
    {
      "name": "cats",
      "description": ""
    }
  ],
  "servers": [],
  "components": {
    "securitySchemes": {
      "bearer": {
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "type": "http"
      }
    },
    "schemas": {
      "CreateCatDto": {
        "type": "object",
        "properties": {}
      },
      "Cat": {
        "type": "object",
        "properties": {
          "age": {
            "type": "number",
            "example": 1,
            "description": "The age of the Cat"
          },
          "breed": {
            "type": "string",
            "example": "Maine Coon",
            "description": "The breed of the Cat"
          }
        },
        "required": [
          "age",
          "breed"
        ]
      }
    }
  },
  "paths": {
    "/cats": {
      "post": {
        "operationId": "CatsController_create",
        "summary": "Create cat",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCatDto"
              }
            }
          }
        },
        "responses": {
          "403": {
            "description": "Forbidden."
          }
        },
        "tags": [
          "cats"
        ],
        "security": [
          {
            "bearer": []
          }
        ]
      }
    },
    "/cats/{id}": {
      "get": {
        "operationId": "CatsController_findOne",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The found record",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Cat"
                }
              }
            }
          }
        },
        "tags": [
          "cats"
        ],
        "security": [
          {
            "bearer": []
          }
        ]
      }
    }
  }
}

Expected behavior

same with: http://localhost:3000/api-json

{
  "swaggerDoc": {
    "openapi": "3.0.0",
    "info": {
      "title": "Cats example",
      "description": "The cats API description",
      "version": "1.0",
      "contact": {}
    },
    "tags": [
      {
        "name": "cats",
        "description": ""
      }
    ],
    "servers": [],
    "components": {
      "securitySchemes": {
        "bearer": {
          "scheme": "bearer",
          "bearerFormat": "JWT",
          "type": "http"
        }
      },
      "schemas": {
        "CreateCatDto": {
          "type": "object",
          "properties": {
            "name": {
              "type": "string"
            },
            "age": {
              "type": "number"
            },
            "breed": {
              "type": "string"
            }
          },
          "required": [
            "name",
            "age",
            "breed"
          ]
        },
        "Cat": {
          "type": "object",
          "properties": {
            "age": {
              "type": "number",
              "example": 1,
              "description": "The age of the Cat"
            },
            "breed": {
              "type": "string",
              "example": "Maine Coon",
              "description": "The breed of the Cat"
            },
            "name": {
              "type": "string",
              "description": "The name of the Cat",
              "example": "Kitty"
            }
          },
          "required": [
            "age",
            "breed",
            "name"
          ]
        }
      }
    },
    "paths": {
      "/cats": {
        "post": {
          "operationId": "CatsController_create",
          "summary": "Create cat",
          "parameters": [],
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateCatDto"
                }
              }
            }
          },
          "responses": {
            "201": {
              "description": "",
              "content": {
                "application/json": {
                  "schema": {
                    "$ref": "#/components/schemas/Cat"
                  }
                }
              }
            },
            "403": {
              "description": "Forbidden."
            }
          },
          "tags": [
            "cats"
          ],
          "security": [
            {
              "bearer": []
            }
          ]
        }
      },
      "/cats/{id}": {
        "get": {
          "operationId": "CatsController_findOne",
          "parameters": [
            {
              "name": "id",
              "required": true,
              "in": "path",
              "schema": {
                "type": "string"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The found record",
              "content": {
                "application/json": {
                  "schema": {
                    "$ref": "#/components/schemas/Cat"
                  }
                }
              }
            }
          },
          "tags": [
            "cats"
          ],
          "security": [
            {
              "bearer": []
            }
          ]
        }
      }
    }
  },
  "customOptions": {},
  "swaggerUrl": {}
}

Minimal reproduction of the problem with instructions

https://github.com/nestjs/nest/tree/master/sample/11-swagger

add a generator script:

import { writeFileSync } from 'fs';
import { resolve } from 'path';
import { NestFactory } from '@nestjs/core';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  const options = new DocumentBuilder()
    .setTitle('Cats example')
    .setDescription('The cats API description')
    .setVersion('1.0')
    .addTag('cats')
    .addBearerAuth()
    .build();
  const document = SwaggerModule.createDocument(app, options);
  // SwaggerModule.setup('api', app, document);
  writeFileSync(
    resolve(__dirname, '../api.json'),
    JSON.stringify(document, null, 2),
    {
      encoding: 'utf-8',
    },
  );
}
bootstrap();

Environment


Nest version:  7.5.4

 
For Tooling issues:
- Node version:  14.15.4
- Platform:  Mac

Others:

@Tony133
Copy link
Contributor

Tony133 commented Jan 7, 2021

hi, @willin you can leave a minimal reproduction of a clonable git repo so the core team can evaluate the problem you reported.

@willin
Copy link
Author

willin commented Jan 8, 2021

@willin
Copy link
Author

willin commented Jan 16, 2021

@Tony133

for the timebeing

#!/usr/bin/env bash

# Generate api.json
mv src/main.ts src/main.ts.bak
cp src/doc.ts src/main.ts
nest start
rm -f src/main.ts
mv src/main.ts.bak src/main.ts

we use this script temporarily

but i have no idea why

@Tony133
Copy link
Contributor

Tony133 commented Jan 16, 2021

Hi @willin, i took a look at your repo to generate a json schema i tried to make some changes

try this in the nest-cli.json file change it like this:

{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "deleteOutDir": true,
    "plugins": ["@nestjs/swagger/plugin"]
  }
}

then in the main.ts file add this line:

  writeFileSync("./ swagger.json", JSON.stringify(document));

the complete file becomes like this:

import {NestFactory} from '@nestjs/core';
import {DocumentBuilder, SwaggerModule} from '@nestjs/swagger';
import {AppModule} from './app.module';
import {writeFileSync} from "fs";

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  const options = new DocumentBuilder()
    .setTitle('Cats example')
    .setDescription('The cats API description')
    .setVersion('1.0')
    .addTag('cats')
    .addBearerAuth()
    .build();
  const document = SwaggerModule.createDocument(app, options);
  writeFileSync("./ swagger.json", JSON.stringify(document));

  SwaggerModule.setup ('api', app, document);

  await app.listen(3000);
  console.log(`Application is running on: $ {await app.getUrl ()}`);
}
bootstrap();

i called it swagger.json but indifferent i took a cue from this problem #158

as soon as you run from terminal npm run start:dev you generate the file automatically.

The json that I generate is the following:

{
  "openapi": "3.0.0",
  "info": {
    "title": "Cats example",
    "description": "The cats API description",
    "version": "1.0",
    "contact": {}
  },
  "tags": [{
    "name": "cats",
    "description": ""
  }],
  "servers": [],
  "components": {
    "securitySchemes": {
      "bearer": {
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "type": "http"
      }
    },
    "schemas": {
      "CreateCatDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "age": {
            "type": "number",
            "example": 1,
            "description": "The age of the Cat"
          },
          "breed": {
            "type": "string",
            "example": "Maine Coon",
            "description": "The breed of the Cat"
          }
        },
        "required": ["name", "age", "breed"]
      },
      "Cat": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "age": {
            "type": "number"
          },
          "breed": {
            "type": "string"
          }
        },
        "required": ["name", "age", "breed"]
      }
    }
  },
  "paths": {
    "/cats": {
      "post": {
        "operationId": "CatsController_create",
        "summary": "Create cat",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCatDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Cat"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden."
          }
        },
        "tags": ["cats"],
        "security": [{
          "bearer": []
        }]
      }
    },
    "/cats/{id}": {
      "get": {
        "operationId": "CatsController_findOne",
        "parameters": [{
          "name": "id",
          "required": true,
          "in": "path",
          "schema": {
            "type": "string"
          }
        }],
        "responses": {
          "200": {
            "description": "The found record",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Cat"
                }
              }
            }
          }
        },
        "tags": ["cats"],
        "security": [{
          "bearer": []
        }]
      }
    }
  }
}

alternatively to generate the file in json you can also create an endpoint that generates the file in json, the endpoint and the following http://localhost: 3000/api-json

Remember, if you want to view everything in swagger you have to add the @ApiProperty decorator for each field you want to view otherwise swagger doesn't display everything.

however if you have difficulty use the discord channel for support

@willin
Copy link
Author

willin commented Jan 17, 2021

@Tony133 i don't want to start up a swagger service at PRODUCTION ENV, so that i need another script to generate api.json standalone.

the thing confuse me is that nest start the script works well, but ts-node src/ not.

@Tony133
Copy link
Contributor

Tony133 commented Jan 17, 2021

@willin Ok I misunderstood, but add a description of your problem to specify it better, so to the eye it seems that your problem is that it does not generate the json file.

@willin
Copy link
Author

willin commented Jan 18, 2021

ts-node src/

search CreateCatDto in the generated json, found:

     "CreateCatDto": {
        "type": "object",
        "properties": {}
      },

nest start

found:

"CreateCatDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "age": {
            "type": "number",
            "example": 1,
            "description": "The age of the Cat"
          },
          "breed": {
            "type": "string",
            "example": "Maine Coon",
            "description": "The breed of the Cat"
          }
        },

@kamilmysliwiec
Copy link
Member

This is the expected behavior. CLI plugins run as part of the nest build build pipeline and it's an exclusive feature of Nest CLI - plugins won't be automatically applied when ts-node is being used.

Please, use our Discord channel (support) for such questions. We are using GitHub to track bugs, feature requests, and potential improvements.

@javiermuniz
Copy link

For anyone that arrived here, like me, and is just looking for a solution, the nest cli has an --entryFile option. This can be used to set the entry file when doing nest start instead of ts-node.

In the exampe repo changing:

"build:doc": "ts-node src/doc.ts",

to:

"build:doc": "nest start --entryFile doc.js",

Should fix the problem.

@bhare1987
Copy link

For anyone that arrived here, like me, and is just looking for a solution, the nest cli has an --entryFile option. This can be used to set the entry file when doing nest start instead of ts-node.

In the exampe repo changing:

"build:doc": "ts-node src/doc.ts",

to:

"build:doc": "nest start --entryFile doc.js",

Should fix the problem.

This has been plaguing me for a while, thank you so much @javiermuniz!!!

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

5 participants