swagger icon indicating copy to clipboard operation
swagger copied to clipboard

NestJS Swagger Plugin when used with SWC references undeclared variable

Open evanwhitten opened this issue 2 years ago • 6 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Current behavior

When @nestjs/swagger CLI plugin is used alongside SWC, it generates output in the metadata.ts from the PluginMetadataGenerator that includes undeclared variables. These variables inside the metadata.ts trigger failures when type checking, also during runtime if the metadata is attempted to be used somewhere like loadPluginMetadata.

In my reproduction I have HelloClass and HelloClassSeperate demonstrating that this bug is only present when the class exists in the same file as the DTO.

✔  TSC  Initializing type checker...
>  TSC  Found 0 issues. Generating metadata...
>  SWC  Running...
Successfully compiled: 8 files with swc (7.99ms)
[Nest] 3860  - 09/26/2023, 4:46:59 PM     LOG [NestFactory] Starting Nest application...
[Nest] 3860  - 09/26/2023, 4:46:59 PM     LOG [InstanceLoader] AppModule dependencies initialized +6ms

/Users/evanwhitten/Git/reproduce-cli-swagger-reference/dist/metadata.js:76
                                        HelloClass
                                        ^
ReferenceError: HelloClass is not defined
    at Object.type (/Users/evanwhitten/Git/reproduce-cli-swagger-reference/dist/metadata.js:76:41)
    at SchemaObjectFactory.mergePropertyWithMetadata (/Users/evanwhitten/Git/reproduce-cli-swagger-reference/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js:127:38)
    at /Users/evanwhitten/Git/reproduce-cli-swagger-reference/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js:82:35
    at Array.map (<anonymous>)
    at SchemaObjectFactory.extractPropertiesFromType (/Users/evanwhitten/Git/reproduce-cli-swagger-reference/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js:81:52)
    at SchemaObjectFactory.exploreModelSchema (/Users/evanwhitten/Git/reproduce-cli-swagger-reference/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js:103:41)
    at ResponseObjectFactory.create (/Users/evanwhitten/Git/reproduce-cli-swagger-reference/node_modules/@nestjs/swagger/dist/services/response-object-factory.js:46:47)
    at /Users/evanwhitten/Git/reproduce-cli-swagger-reference/node_modules/@nestjs/swagger/dist/explorers/api-response.explorer.js:67:101
    at /Users/evanwhitten/Git/reproduce-cli-swagger-reference/node_modules/lodash/lodash.js:13469:38
    at /Users/evanwhitten/Git/reproduce-cli-swagger-reference/node_modules/lodash/lodash.js:4967:15

metadata.ts -> Problem area: { required: true, type: () => [HelloClass] }

export default async () => {
    const t = {
        ["./seperate.dto"]: await import("./seperate.dto"),
        ["./app.dto"]: await import("./app.dto")
    };
    return { "@nestjs/swagger": { "models": [[import("./seperate.dto"), { "HelloClassSeperate": { name: { required: true, type: () => String } } }], [import("./app.dto"), { "GetHelloDto": { hello: { required: true, type: () => [HelloClass] } }, "GetHelloSeperateDto": { hello: { required: true, type: () => [t["./seperate.dto"].HelloClassSeperate] } } }]], "controllers": [[import("./app.controller"), { "AppController": { "getHello": { type: t["./app.dto"].GetHelloDto }, "getHelloSeperate": { type: t["./app.dto"].GetHelloSeperateDto } } }]] } };
};

Minimum reproduction code

https://github.com/evanwhitten/reproduce-cli-swagger-reference

Steps to reproduce

  1. nest start -b swc --type-check -> view error from invalid metadata.ts generated

Expected behavior

Expected to have Swagger definitions generated the same as when running the app without SWC.

Without SWC Screenshot 2023-09-26 at 4 36 46 PM

With SWC Screenshot 2023-09-26 at 4 37 39 PM

Package

  • [ ] I don't know. Or some 3rd-party package
  • [ ] @nestjs/common
  • [ ] @nestjs/core
  • [ ] @nestjs/microservices
  • [ ] @nestjs/platform-express
  • [ ] @nestjs/platform-fastify
  • [ ] @nestjs/platform-socket.io
  • [ ] @nestjs/platform-ws
  • [ ] @nestjs/testing
  • [ ] @nestjs/websockets
  • [X] Other (see below)

Other package

@nestjs/swagger

NestJS version

10.2.6

Packages versions

  "dependencies": {
    "@nestjs/common": "^10.0.0",
    "@nestjs/core": "^10.0.0",
    "@nestjs/platform-express": "^10.0.0",
    "@nestjs/swagger": "^7.1.12",
    "reflect-metadata": "^0.1.13",
    "rxjs": "^7.8.1"
  },
  "devDependencies": {
    "@nestjs/cli": "^10.0.0",
    "@nestjs/schematics": "^10.0.0",
    "@nestjs/testing": "^10.0.0",
    "@swc/cli": "^0.1.62",
    "@swc/core": "^1.3.89",
    "@types/express": "^4.17.17",
    "@types/jest": "^29.5.2",
    "@types/node": "^20.3.1",
    "@types/supertest": "^2.0.12",
    "@typescript-eslint/eslint-plugin": "^5.59.11",
    "@typescript-eslint/parser": "^5.59.11",
    "eslint": "^8.42.0",
    "eslint-config-prettier": "^8.8.0",
    "eslint-plugin-prettier": "^4.2.1",
    "jest": "^29.5.0",
    "prettier": "^2.8.8",
    "source-map-support": "^0.5.21",
    "supertest": "^6.3.3",
    "ts-jest": "^29.1.0",
    "ts-loader": "^9.4.3",
    "ts-node": "^10.9.1",
    "tsconfig-paths": "^4.2.0",
    "typescript": "^5.1.3"
  },

Node.js version

v18.16.1

In which operating systems have you tested?

  • [X] macOS
  • [ ] Windows
  • [ ] Linux

Other

No response

evanwhitten avatar Sep 26 '23 22:09 evanwhitten

I believe I have narrowed this down to these lines, however it seems to be above my TS abilities to triage further.

https://github.com/nestjs/swagger/blob/master/lib/plugin/visitors/model-class.visitor.ts#L186-L193

evanwhitten avatar Sep 26 '23 22:09 evanwhitten

@evanwhitten, I faced the same problem.

The problem occurs because the required dtos are not exported from the files. Here's how to get a list of dto to export: clear;yarn tsc --noEmit --pretty false | cut -d: -f '3' | sed -Ee "s/.*'(.*)'.*/\1/g" | sort | uniq

And here is a regular expression to add exports throughout the project (in parentheses you need to substitute your dto names without exports): find ./ -type f -exec sed -i -Ee "/export /! s/(class DtoWithoutExportOne|class DtoWithoutExportTwo)/export \1/g" {} \;

utrumo avatar Oct 06 '23 15:10 utrumo

I have same issue, any updates?

m0x61h0x64i avatar Dec 14 '23 11:12 m0x61h0x64i

I have same issue, any updates?

As mentioned by @utrumo, you can workaround this by exporting the class.

In my example exporting this class , resolves the error.

evanwhitten avatar Dec 14 '23 13:12 evanwhitten

@evanwhitten That does not solve the issue, dto classes are already being exported

m0x61h0x64i avatar Dec 14 '23 23:12 m0x61h0x64i

Hello, I also encountered the same problem, but I used the method you provided and it did not solve the problem.

@evanwhitten That does not solve the issue, dto classes are already being exported这并不能解决问题,dto类已经被导出。

czfadmin avatar Mar 18 '24 11:03 czfadmin