NestJS の DTO と Validation の使い方

次の記事と同じことを行いました。
[NestJS の DTO と Validation の基本 - 型定義とデコレータで安全にデータを受け付ける](https://qiita.com/potato4d/items/d22a14ff6fb82d63c742)

この例は、POST の引数に、title, body, deltePassword の３つの string が総てあるかを判定するものです。

クライアントからアクセスして、次のような結果を得ます。

1) title だけを与えた場合

```text
$ http post http://localhost:3000/items title="test"
HTTP/1.1 400 Bad Request
Connection: keep-alive
Content-Length: 174
Content-Type: application/json; charset=utf-8
Date: Fri, 19 Feb 2021 05:20:10 GMT
ETag: W/"ae-+h15n4beEBei89GgqZrcmN+Lfxs"
Keep-Alive: timeout=5
X-Powered-By: Express

{
    "error": "Bad Request",
    "message": [
        "body must be a string",
        "body should not be empty",
        "deletePassword must be a string",
        "deletePassword should not be empty"
    ],
    "statusCode": 400
}
```

2) title と body を与えた場合

```text
$ http post http://localhost:3000/items title="test" body="aaa"
HTTP/1.1 400 Bad Request
Connection: keep-alive
Content-Length: 123
Content-Type: application/json; charset=utf-8
Date: Fri, 19 Feb 2021 05:20:56 GMT
ETag: W/"7b-i4GKHhtUV3QgQ61LezFhW/XBQsU"
Keep-Alive: timeout=5
X-Powered-By: Express

{
    "error": "Bad Request",
    "message": [
        "deletePassword must be a string",
        "deletePassword should not be empty"
    ],
    "statusCode": 400
}
```

3) title, body, deletePassword を与えた場合

```text
$ http post http://localhost:3000/items title="test" body="aaa" deletePassword="bbb"
HTTP/1.1 201 Created
Connection: keep-alive
Content-Length: 4
Content-Type: text/html; charset=utf-8
Date: Fri, 19 Feb 2021 05:21:42 GMT
ETag: W/"4-X/5TO4MPCKAyY0ipFgr6/IraRNs"
Keep-Alive: timeout=5
X-Powered-By: Express

true
```

サーバーの構築

```bash
nest new validation
cd validation
npm run start
```

クライアントから http://localhost:3000 にアクセスして、
Hello World! が出ることを確認。

ソースコードを追加、改造します。

```bash
mkdir src/items
```

```ts:src/items/items.controller.ts
import { Controller, Post, Body } from '@nestjs/common';
import { CreateItemDTO } from './items.dto';


@Controller('items')
export class ItemsController {
  @Post()
  createItem(@Body() createItemDTO: CreateItemDTO) {
    return true;
  }
}
```

```ts:src/items/items.dto.ts
import { IsNotEmpty, IsString } from 'class-validator';

export class CreateItemDTO {

  @IsNotEmpty()
  @IsString()
  title: string;

  @IsNotEmpty()
  @IsString()
  body: string;

  @IsNotEmpty()
  @IsString()
  deletePassword: string;
}
```

```ts:src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ItemsController } from './items/items.controller';

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

```ts:src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000);
}
bootstrap();
```

src は次のような構造になります。

```text
$ tree src
src
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── items
│   ├── items.controller.ts
│   └── items.dto.ts
└── main.ts
```

ライブラリーのインストール

```bash
npm install class-validator
npm install class-transformer
```

サーバーの起動

```bash
npm run start
```

クライアントからアクセスすると、冒頭の結果が得られます。