NestJS CLIで初心者でも簡単にNode.js REST APIが作れる！

Node.jsなんてほとんど使ったことがないのに、頑張って[NestJS](https://nestjs.com/)でCLIを使ってREST APIを作りました。
あまりドキュメントなかったことに加えて私のスキル不足で半日ほどかかってしまいましたが慣れれば30分もかからないです。

# 環境
Ubuntu18.04.01 LTSで動かしました。
NEST CLIの`nest info`でバージョン情報を見ます。

```bash
$ nest info

 _   _             _      ___  _____  _____  _     _____
| \ | |           | |    |_  |/  ___|/  __ \| |   |_   _|
|  \| |  ___  ___ | |_     | |\ `--. | /  \/| |     | |
| . ` | / _ \/ __|| __|    | | `--. \| |    | |     | |
| |\  ||  __/\__ \| |_ /\__/ //\__/ /| \__/\| |_____| |_
\_| \_/ \___||___/ \__|\____/ \____/  \____/\_____/\___/


[System Information]
OS Version     : Linux 4.15
NodeJS Version : v12.14.1
NPM Version    : 6.13.4 

[Nest CLI]
Nest CLI Version : 6.14.2 

[Nest Platform Information]
platform-express version : 6.10.14
common version           : 6.10.14
core version             : 6.10.14
```

# 手順
[NestJS 入門](https://nananao-dev.hatenablog.com/entry/nestje-introduction)を参考にしました。作ったプログラムは[GitHub](https://github.com/YoheiFukuhara/node-nest-rest)に置いてあります。

## 1. プロジェクト作成
`nest new <プロジェクト名>`でプロジェクトを作ります。

```bash
$ nest new nest-test
⚡  We will scaffold your app in a few seconds..

CREATE /nest-test/.eslintrc.js (599 bytes)
CREATE /nest-test/.prettierrc (51 bytes)
CREATE /nest-test/README.md (3370 bytes)
CREATE /nest-test/nest-cli.json (64 bytes)
CREATE /nest-test/package.json (1877 bytes)
CREATE /nest-test/tsconfig.build.json (97 bytes)
CREATE /nest-test/tsconfig.json (336 bytes)
CREATE /nest-test/src/app.controller.spec.ts (617 bytes)
CREATE /nest-test/src/app.controller.ts (274 bytes)
CREATE /nest-test/src/app.module.ts (249 bytes)
CREATE /nest-test/src/app.service.ts (142 bytes)
CREATE /nest-test/src/main.ts (208 bytes)
CREATE /nest-test/test/app.e2e-spec.ts (630 bytes)
CREATE /nest-test/test/jest-e2e.json (183 bytes)

? Which package manager would you ❤️  to use? npm
✔ Installation in progress... ☕

🚀  Successfully created project nest-test
👉  Get started with the following commands:

$ cd nest-test
$ npm run start
```

## 2. プロジェクト作成確認
プロジェクト作成時の指示に従い、nodeを起動します。

```bash
$ cd nest-test
$ npm run start
```

起動したのでcurlで確かめてみます。"Hello World!"を取得できました。もちろんブラウザでアクセスしても同じ結果です。

```bash
$ curl http://localhost:3000
Hello World! 
```

## 3. Module作成
CLIから`nest generate module <モジュール名>`でModuleを生成。今回はModuleなどをすべて`test`で統一しています。

```bash
nest generate module test
CREATE /src/test/test.module.ts (81 bytes)
UPDATE /src/app.module.ts (308 bytes)
```

## 4. Interface作成
CLIから`nest generate interface <インターフェース名>`でInterfaceを生成。インタフェースはフォルダ付きで"test/test"にしています。他と違うので気持ち悪いのですが、こんなものなのでしょうか。

```bash
nest generate interface test/test
CREATE /src/test/test.interface.ts (25 bytes)
```

生成された`test.interface.ts`を修正します。Interfaceに型を定義します。

```ts:test.interface.ts
export interface Test {
    id: string;
    name: string;
}
```

## 5. Service作成
CLIから`nest generate service <サービス名>`でServiceを生成。

```bash
$ nest generate service test
CREATE /src/test/test.service.spec.ts (446 bytes)
CREATE /src/test/test.service.ts (88 bytes)
UPDATE /src/test/test.module.ts (155 bytes)
```

手で`test.service.ts`を修正します。複数のTestを出力する関数`listTest`とidを指定して単一のTestを返す関数`getTest`を定義します。

```ts:test.service.ts
import { Injectable } from '@nestjs/common';
import { Test } from './test.interface';

@Injectable()
export class TestService {
  private readonly test: Test[] = [{id: 'a', name: 'Alex'}, {id: 'b', name: 'Bob'}, {id: 'c', name: 'Cathy'}];

  listTest(): Test[] {
    return this.test;
  }

  getTest(id: string): Test {
    return this.test.find(value => value.id === id);
  }
}
```

## 6. Controller作成
CLIから`nest generate controller <コントローラー名>`でControllerを生成。

```bash
$ nest generate controller test
CREATE /src/test/test.controller.spec.ts (479 bytes)
CREATE /src/test/test.controller.ts (97 bytes)
UPDATE /src/test/test.module.ts (240 bytes)
```

`test.controller.ts`を修正。先ほどサービス内で定義した関数を呼び出します。
`@Controller('test')`とすることでパス`test`にアクセスしたときに動作するようにしています。`@Get()`としたことでGETメソッドでアクセスしたときに動作します。`@Get(':id')`は、パス`test`の配下に指定したidを受け取ります。

```ts:test.controller.ts
import { Controller, Get, Param } from '@nestjs/common';
import { TestService } from './test.service';
import { Test } from './test.interface';

@Controller('test')
export class TestController {
    constructor(private readonly testService: TestService) {}

    @Get()
    listUsers(): Test[] {
      return this.testService.listTest();
    }
  
    @Get(':id')
    getTest(@Param('id') id: string): Test {
      return this.testService.getTest(id);
    }      
}
```

## 7. 起動と確認
テストのためにnodeを起動。

```bash
nest start
```

curlで結果を確認します。無事、リスポンスを取得できました。

```bash
$ curl http://localhost:3000
Hello World

$ curl http://localhost:3000/test
[{"id":"a","name":"Alex"},{"id":"b","name":"Bob"},{"id":"c","name":"Cathy"}]

$ curl http://localhost:3000/test/a
{"id":"a","name":"Alex"}
```

## 8. ビルド
最後に`nest build`で`dist`フォルダ配下にコードをビルドします。

```bash
nest build
```