OpenAPI Generator で NestJS と Angular をタイプセーフに繋ぐ

本記事は、以下の記事の内容を Spring Boot から NestJS に置き換えたものです。
[OpenAPI Generator で Spring Boot と Angular をタイプセーフに繋ぐ](https://qiita.com/chibato/items/e4a748db12409b40c02f)

## 課題になっていたこと

Web バックエンドと Web フロントエンドで、JSON でボヤッっと緩く通信している状況が怖かった。
ビルド時にできるだけ、問題を検出したかった。
RPC的にタイプセーフに通信できるようにしたかった。

## OpenAPI Generator について

[OpenAPI Generator](https://openapi-generator.tech) や Swagger Codegen は、REST API の仕様を基にクライアントコードや、サーバのスタブコードを生成するツールです。
残念なことに Swagger Codegen の運営？に問題があったらしく、トップコントリビュータによりフォークされ、OpenAPI Generator が誕生していました。
現状は、OpenAPI Generator の方が、コミット数、コントリビュータ数も多い状況です。
今回、 OpenAPI Generator を利用しています。

## NestJS について
https://docs.nestjs.com/
NestJS は、TypeScript 製の Web バックエンドのフレームワークです。
Java の Spring MVC に似ており、メソッドのシグネチャーから REST API の仕様が読み取りやすくなっています。

## 作ったもの

雛形プロジェクトです。
https://github.com/chibat/nestjs-openapi-angular-starter

## プロジェクトの構成

<img src="https://docs.google.com/drawings/d/e/2PACX-1vTNkQFzfRmMoJqEkbVtJXWgwMNgJXJQRiQEjmNajjpYUQboE3syxos7EbMsrpBL8j9WFmyjJCto2sD5/pub?w=632&h=367">

OpenAPI の Spec ファイルは、自動で生成されるため手動で作成する必要がありません。


## 開発フロー

雛形プロジェクトに含まれる簡単な足し算アプリを例に説明します。

### 1. Web バックエンドの作成

Web バックエンドは、NestJS で作成します。

#### app.controller.ts

２つの整数をリクエストで受け取り、足してレスポンスするだけの Controller クラスです。

```typescript
import { Controller, Post, Body, HttpCode } from '@nestjs/common';
import { RequestDto } from './request.dto';
import { ResponseDto } from './response.dto';
import { ApiResponse, ApiOperation, ApiUseTags } from '@nestjs/swagger';

@Controller('rest/api')
@ApiUseTags('calculate')
export class AppController {

  @Post('add')
  @HttpCode(200)
  @ApiOperation({title: "", operationId: "add"})
  @ApiResponse({
    status: 200,
    type: ResponseDto
  })
  add(@Body() request: RequestDto): ResponseDto {
    return {result: request.arg1 + request.arg2};
  }
}
```

#### request.dto.ts
```typescript
import { ApiModelProperty } from "@nestjs/swagger";

export class RequestDto {

  @ApiModelProperty()
  readonly arg1: number;

  @ApiModelProperty()
  readonly arg2: number;
}
```

#### response.dto.ts
```typescript
import { ApiModelProperty } from "@nestjs/swagger";

export class ResponseDto {

  @ApiModelProperty()
  result: number;
}
```

Spring Boot のアノテーションと比較すると、NestJS のデコレータは多めになります。
ApiModelProperty とか省略できるようになればなーと思ったりします。

### 2. Web フロントエンドのクライアントコードの生成

npm タスクを実行し、クライアントコードを生成します。

```
$ cd backend
$ npm run generate-client
```

NestJS のコードを調べていたところ、 OpenAPI Spec の JSON が簡単にファイルに出力できることが分かりました。
そのファイルを OpenAPI Generator が読み込み、クライアントコードを生成します。

### 3. Web フロントエンドの作成

Web フロントエンドは、 Angular で作成します。
生成したクライアントコードを利用する Component クラスを作成します。
CalculatorService が自動生成されたクラスです。

```typescript
import { Component } from '@angular/core';
import { CalculatorService } from './client/api/calculator.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  arg1: number;
  arg2: number;
  result: number;

  constructor(private  calculatorService: CalculatorService) {
  }

  add() {
    if (this.arg1 || this.arg2) {
      this.calculatorService
        .add({arg1: this.arg1, arg2: this.arg2})
        .subscribe(data => this.result = data.result);
    }
  }
}
```

## まとめ

バックエンド、フロントエンドが両方 TypeScript なので、 DTO を共有するだけでもある程度タイプセーフになるかもしれませんが、OpenAPI Generator を利用することで、よりタイプセーフになるかと思います。

以上、快適なタイプセーフライフをお楽しみください。

## OpenAPI Generator の電子書籍が発売されました！（2019-09-19 追記）

OpenAPI Generator の電子書籍が発売されました。
興味のある方は、ご購入してみてはいかがでしょうか。

[REST API のためのコード生成入門 (OpenAPI Generator) ](https://gumroad.com/l/openapi_generator_ebook_jp)
<a href="https://gumroad.com/l/openapi_generator_ebook_jp"><img src="https://static-2.gumroad.com/res/gumroad/3680469107511/asset_previews/f359f63a4feaf3abf15e1046515adf79/retina/ebook_20cover_20japanese-page-001.jpg" width="300px"></a>