LoginSignup
2
0

More than 3 years have passed since last update.

nestjs/swagger 3系(Swagger2.0)⇒4系(Swagger3.0(OpenAPI))へのバージョンアップ

Posted at

Nest.jsのSwaggerが3.0(OpenAPI)に対応するぞ!!!」でも記載しましたが、nestjs/swaggerの4系がリリースされ、正式にSwagger3.0(OpenAPI)に対応しました!!!

今回は、nestjs/swaggerの3系から4系へのバージョンアップしたときの手順を備忘録がてら書いておこうと思います。

nestjs/swaggerのバージョンアップ

nestjs/swaggerの最新版をインストールします

npm i --save @nestjs/swagger@latest 

コードの修正

アノテーションの変更

リファレンスにも書いてありますが、いくつかアノテーションが変更になっているため、置換します。

The following decorators have been changed/renamed:

  • @ApiModelProperty is now @ApiProperty
  • @ApiModelPropertyOptional is now @ApiPropertyOptional
  • @ApiResponseModelProperty is now @ApiResponseProperty
  • @ApiImplicitQuery is now @ApiQuery
  • @ApiImplicitParam is now @ApiParam
  • @ApiImplicitBody is now @ApiBody
  • @ApiImplicitHeader is now @ApiHeader
  • @ApiOperation({ title: 'test' }) is now@ApiOperation({ summary: 'test' })
  • @ApiUseTags is now @ApiTags

@ApiOperationだけは、なぜかオプションのプロパティ名が変更になっているため注意です。

DocumentBuilderのオプション変更

DocumentBuilderにて、いくつかの関数が変更/追加/削除されているため対応します。

DocumentBuilder breaking changes (updated method signatures):

  • addTag
  • addBearerAuth
  • addOAuth2
  • setContactEmail is now setContact
  • setHost has been removed
  • setSchemes has been removed

The following methods have been added:

  • addServer
  • addApiKey
  • addBasicAuth
  • addSecurity
  • addSecurityRequirements

setGlobalPrefixを使っている場合

リファレンスに記載がありますが、GlobalPrefixを使っている場合はオプションでignoreGlobalPrefix: trueを指定する必要があります。

これを指定しないと、http://localhost:3000/api/api/helloみたいにプレフィクスが重複します。

↓修正例

const apiPrefix = '/api/v1';
app.setGlobalPrefix(apiPrefix);

const options = new DocumentBuilder()
    ・・・
    .addServer(apiPrefix)
    .build();

SwaggerModule.createDocument(app, options, { ignoreGlobalPrefix: true });

プラグインの設定

プラグインがいくつか使えるようになりました。
これにより、DTOクラスにアノテーションを指定する必要がなくなったり、class-validatorのいくつかのアノテーションをSwaggerに取り込んでくれるようになります。

nestjs-cli.json
{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "plugins": [
      {
        "name": "@nestjs/swagger/plugin",
        "options": {
          "classValidatorShim": true
        }
      }
    ]
  }
}

オプションとして、以下を指定することができます

  • dtoFileNameSuffix:dtoファイルのサフィックスを指定できます(デフォルトは.dto.ts,.entity.ts
  • controllerFileNameSuffix:コントローラーファイルのサフィックスを指定できます(デフォルトは.controller.ts
  • classValidatorShimclass-validatorのアノテーションを有効にする場合はtrue(デフォルトはfalse)
    • バリデーションについてはこちらを参照

openapi-generatorを使ってAPIクライアントを生成している場合

nestjs/swagger3系で出力されるSpecファイルを使っていた場合、生成されるAPIクライアントの関数名はデフォルトで{パス}{メソッド}でした。

4系になり、operationIdにコントローラーの関数名がセットされ、その名称でAPIクライアントが生成されるため、クライアントサイドでfunction not foundが大量に発生しました。。。

【バージョンごとの出力例】

バージョン URL メソッド コントローラーの関数名 出力されるAPIクライアント
3系 /hello/world GET getMessage() helloWorldGet()
4系 /hello/world GET getMessage() getMessage()

対応

  1. @ApiOperationoperationIdを指定する
  2. コントローラーの関数名を元のAPIクライアント名に変更
  3. コントローラーの関数名でクライアントサイドの呼び出し箇所を置換する

幸いまだリリース前のプロジェクトで大幅な変更も受け付けられるので3を採用しました。

バグ?

DTOファイルでエンティティファイルをインポートすると、リファレンスエラーになりました。
対象ファイル(ビルド後)は↓のような感じで、test_entity_1.defaultがないと怒られます。

test.dto.js
Object.defineProperty(exports, "__esModule", { value: true });
const openapi = require("@nestjs/swagger");
const class_validator_1 = require("class-validator");
class TestDto {
}
__decorate([
    openapi.ApiProperty({ required: true, type: () => require("../models/test.entity").default }),
    __metadata("design:type", test_entity_1.default)
], TestDto.prototype, "apply", void 0);

よく見るとrequire("../models/test.entity")をtest_entity_1に設定する処理がありません。。。

とりあえず、@ApiProperty({type: Test})のように直接型を指定すれば回避できますが、イケてないですね。。。
そもそもエンティティファイルをDTOファイルでインポートするな!ということなんでしょうか?

今後のバージョンアップに期待しましょう。

まとめ

割と簡単にバージョンアップができました。
今回のバージョンアップでOpenAPIに対応しただけじゃなく、DTOやレスポンス等の一部のアノテーションを省略できるようになったのはかなり大きいと思います。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0