NestJSでAPIを作る

今回からNestでバックエンド側の作成を始めて行きます。

# APIを作る
APIを作るのは案外簡単です。
moduleとコントローラー(とサービス)を書くだけです。

それでは始めていきます
# ディレクトリ構造

```
src/
├── app.module.ts
├── main.ts
├── controllers/
│   ├── app.controller.ts
│   └── match-data.controller.ts
├── services/
│   ├── app.service.ts
│   └── match-data.service.ts
└── modules/
    └── match-data.module.ts
```

今回はこのようなディレクトリ構造にしました。初心者なのでこういう分け方は良くなかったりするかもしれないですがとりあえずこのディレクトリ構造で行きます。後で変えるかもしれません。

それでは実際にAPIを作ってみましょう

# moduleの設定

```match-data.modules.ts

import { Module } from '@nestjs/common';
import { MatchDataController } from 'controller/match-data/match-data.controller';
import { MatchDataService } from 'feature/match-data/match-data.service';

@Module({
    controllers: [MatchDataController],
    providers: [MatchDataService],
})
export class MatchDataModule { }
```

`MatchDataController`が`MatchDataService`を使うよ！という意味です。
例えば他のサービスなどを使いたい場合は`providers: [MatchDataService, HogeService],`みたいに書きましょう。多分そのうち書くと思います。

それでは`MatchDataController`と`MatchDataService`を書いていきます。

# コントローラーの設定

``` match-data.controller.ts
import { Controller, Get } from '@nestjs/common';
import { ApiOkResponse, ApiOperation, ApiResponse } from '@nestjs/swagger';
import { MatchDataService } from 'feature/match-data/match-data.service';
import { WinRate } from 'feature/match-data/win-rate.dto';


@Controller('match-data')
export class MatchDataController {
    constructor(private readonly matchDataService: MatchDataService) { }

    @Get('/win-rate')
    @ApiOperation({ summary: '勝率データを取得します' })
    @ApiResponse({ status: 200, description: '勝率データが返却されました' })
    @ApiOkResponse({ description: '勝率のデータ', type:[WinRate]})
        
    async getWinRate(): Promise<WinRate[]> {
        // return this.matchDataService.getWinRates();
        return []
    }
}
```

全く話していませんでしたが今回はマッチデータの集計などのアプリケーションを作る予定です。
本プロジェクトではswaggerも使います。swaggerはAPIがちゃんとできているか確認するのに便利です。

では一つずつ何をしているか見ていきましょう

### `@Controller('match-data')`
これは`/match-data`のエンドポイントだよ～って事を表しています。

### `constructor(private readonly matchDataService: MatchDataService) {}`
見ての通りにはなりますが`MatchDataService`のインスタンス`matchDataService`を定義しています。`matchDataService`は次の記事で作ります。

### `@Get('/win-rate')`
これはエンドポイントの定義です。以下のswaggerのドキュメントデコレーターと書き方は同じですが(同じデコレーターだから)これは大事というか必要なヤツです。
`/win-rate`のGETメソッドということを表しています。`@Controller('match-data')`と合わせると`/match-data/win-rate`のGETメソッドという意味になります。
### `@ApiOperation({ summary: '勝率データを取得します' })`
これはswaggerドキュメントのデコレーターです。swaggerで見たときに何をするかを表示してくれます。
### `@ApiResponse({ status: 200, description: '勝率データが返却されました' })`
これもswaggerのドキュメントです。何が返ってくるかを表すものとします。
### `@ApiOkResponse({ description: '勝率のデータ', type:[WinRate]})`
同じくswaggerのドキュメントです。APIの正常な(200レスポンス)の返却値の型を明記します。
`WinRate` は定義しないと行けないのですがそれはまた次回


以上のデコレーターなどからこのAPIは`/match-data/win-rate`のGETメソッドで`勝率データを取得する`ためのAPIで200で、`WinRateの配列`を勝率データとして返却するものだとわかります。

```
    async getWinRate(): Promise<WinRate[]> {
        // return this.matchDataService.getWinRates();
        return []
    }
```
ここは普通の関数です。機能というか実際の処理はサービス側で記述し、実行することになります。

最後に`app.module.ts`に追加の記述をします。
```app.module.ts

@Module({
  imports: [MatchDataModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

```
Nestは`app.module`を最初に見るみたいなのでそこに`imports`として先ほど作った`MatchDataModule`を足しましょう。これをしないと機能してくれません。


機能については次回の記事で書いていくので本記事ではこれで正しく`[]`が返却されることを確認して終わります。

swaggerと実際にページを開く2つの方法で確認していきます

# APIの確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946470/074bb152-342b-b46e-6931-d881a3c20adb.png)

こんな感じでresponse bodyが`[]`で返ってきているのが確認できます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946470/6bf75953-2104-3309-a8ca-79455e67949a.png)

ブラウザでアクセスしても同様に値が返却されているのがわかると思います。

これでAPIが作成できました。次回は機能の実装を行います。