如何在 Nx monorepo 中为 NestJS 和 Angular 之间共享的 API 接口启用 Swagger?

Posted

技术标签:

【中文标题】如何在 Nx monorepo 中为 NestJS 和 Angular 之间共享的 API 接口启用 Swagger?【英文标题】:How to enable Swagger for API interfaces shared between NestJS and Angular within Nx monorepo? 【发布时间】:2020-08-26 11:03:04 【问题描述】:

我想为 API 接口启用 Swagger,在 Nx monorepo 内的 NestJS 和 Angular 应用程序之间共享。有没有一种一致且看起来不是变通办法的方法?

这些是我没有成功的方法:

方法 1. 将 @nestjs/swagger 装饰器应用于共享 DTO 类

使用npx create-nx-workspace@latest 创建一个新的 Nx monorepo 选择angular-nest 工作区蓝图 安装 Swagger 依赖并根据guide 引导它 在app.component.ts 中添加Message 类型的输入(没有意义,仅用于测试):
export class AppComponent 
  @Input() message: Message;

  hello$ = this.http.get<Message>('/api/hello');
  constructor(private http: HttpClient) 

ApiProperty()api-interfaces.ts 中装饰message 属性:
import  ApiProperty  from '@nestjs/swagger';

export class Message 
  @ApiProperty()
  message: string;

运行 NestJS 应用程序。它工作正常,Swagger 在 Web 视图中显示正确的 DTO 结构 但是,当我启动 Angular 应用程序时,出现错误:
WARNING in ./node_modules/@nestjs/common/utils/load-package.util.js 8:39-59
Critical dependency: the request of a dependency is an expression

WARNING in ./node_modules/express/lib/view.js 81:13-25
Critical dependency: the request of a dependency is an expression

WARNING in ./node_modules/@nestjs/mapped-types/dist/type-helpers.utils.js
Module not found: Error: Can't resolve 'class-transformer' in '.\node_modules\@nestjs\mapped-types\dist'

ERROR in ./node_modules/@nestjs/common/cache/cache.providers.js
Module not found: Error: Can't resolve 'cache-manager' in '.\node_modules\@nestjs\common\cache'
ERROR in ./node_modules/@nestjs/common/pipes/validation.pipe.js
Module not found: Error: Can't resolve 'class-transformer' in '.\node_modules\@nestjs\common\pipes'
...

这看起来像是一个捆绑问题,类似于 this one。我还没有找到任何优雅的工作解决方案来在 Angular 构建中修复它。

方法 2. 使用 NestJS Swagger plugin 并避免使用装饰器

这甚至会比上一个更好,但它并没有奏效。首先,Swagger 插件需要 NestJS CLI,而在 Nx monorepo 中则不然。有一个issue 建议了一些解决方法,但我还没有发现它们足够可靠和完整。其次,该插件没有涵盖一些重要的用例,这些用例仍然需要装饰器。例如:

@ApiProperty(
  oneOf: [ $ref: getSchemaPath(TypeA) ,  $ref: getSchemaPath(TypeB) ],
)
type: TypeA | TypeB;

如上所述,装饰器会导致错误。

方法 3. 从 DTO 类中创建接口以供 Angular 应用程序专用

这种方法吸引我的是能够从后端特定逻辑(Swagger、序列化或验证装饰器)中抽象出来。我们可以这样做:

// Expose to the back-end
export class MessageDto 
  @ApiProperty()
  message: string;


// Expose to the front-end
export interface Message extends MessageDto 

在这种情况下,Message 接口可以很好地与 Angular 应用程序一起编译。但是一旦我们引入更复杂的 DTO 组合(具有嵌套 DTO 的类),这种方法就不起作用了。

如果有任何其他想法,我将不胜感激。

【问题讨论】:

这可能是一个完整的解决方法(也不是解决方案),如果您在 NestJS 端启用 Swagger,那么您可能希望使用 3rd 方工具生成 API,而不是共享接口Angular 端的存根使用以下工具:nswag、swagger-codegen、ng-openapi-gen 等...这些工具将swagger.json 文件作为输入 谢谢@ChauTran!除非我设法使它与上述堆栈一起使用,否则这是一个很好的方法。我将深入研究这些工具以及使它们自动化的能力。 【参考方案1】:

我已成功在 Angular 和 Nest.js 之间共享 DTO(方法 #1)

@angular-devkit/build-angular:browser 替换为 @angular-builders/custom-webpack:browser 已解决构建或提供 Angular 应用程序时的错误。

更多详情请见https://github.com/nestjs/nest/issues/1706#issuecomment-474657479。

【讨论】:

【参考方案2】:

作为简单的解决方法,您可以使用 ApiModelProperty 装饰器而不是 ApiProperty:

import  ApiModelProperty  from '@nestjs/swagger/dist/decorators/api-model-property.decorator';

ApiModelProperty 不会导致缓存管理器注入问题,并且装饰器将允许您为 DTO 设置 API 文档。

【讨论】:

对不起,我试过这个,我得到以下错误 Module not found: Can't resolve '@nestjs/swagger/dist/decorators/api-model-property.decorator' 如果我添加依赖项,他们会再次要求缓存管理器依赖项:S

以上是关于如何在 Nx monorepo 中为 NestJS 和 Angular 之间共享的 API 接口启用 Swagger?的主要内容,如果未能解决你的问题,请参考以下文章

Nx Monorepo NestJS TypeORM SQLite:无法连接到数据库

Nx-NestJS-TypeOrm: SyntaxError: Unexpected token

在 nx 构建/部署上生成 package.json

nrwl/nx 如何使用 npm 发布 NestJs 库?

NestJs monorepo 共享库注入

如何在 Angular / nx 工作区的上下文中运行 nestjs-console 命令