高瀬博道の技術ブログ

高瀬博道の技術ブログです。

もう2023年になったので、今さらNestJSに入門しようと思う - その12

前回

takasehiromichiex.com

オブジェクトスキーマを検証するパイプ

バリデーションの1つとして、スキーマベースのパイプを作成してみましょう。

joiライブラリを使用します。

$ npm install --save joi

カスタムパイプを作成します。

$ nest g pipe pipe/JoiValidation

以下のファイルが作成されました。

src/pipe/joi-validation/joi-validation.pipe.ts
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common';

@Injectable()
export class JoiValidationPipe implements PipeTransform {
  transform(value: any, metadata: ArgumentMetadata) {
    return value;
  }
}
src/pipe/joi-validation/joi-validation.pipe.spec.ts
import { JoiValidationPipe } from './joi-validation.pipe';

describe('JoiValidationPipe', () => {
  it('should be defined', () => {
    expect(new JoiValidationPipe()).toBeDefined();
  });
});

カスタムパイプを修正します。

src/pipe/joi-validation/joi-validation.pipe.ts
import { ArgumentMetadata, BadRequestException, Injectable, PipeTransform } from '@nestjs/common';
import { ObjectSchema } from 'joi';

@Injectable()
export class JoiValidationPipe implements PipeTransform {
  constructor(private schema: ObjectSchema) {}

  transform(value: any, metadata: ArgumentMetadata) {
    const {error} = this.schema.validate(value);

    if (error) {
      throw new BadRequestException('Validation failed.');
    }

    return value;
  }
}

Joiで定義されたスキーマを受け取り、そのスキーマをvalidateして、エラーが出ればthrowするコードです。

スキーマを定義します。

手動でスキーマを作成します。

src/schema/cat/cat.schema.ts
const Joi = require('joi');

export const createCatSchema = Joi.object({
    name: Joi.string().required(),
    age: Joi.number().required(),
    breed: Joi.string().required(),
});

※importだとJoiが動きませんでした。Babelの問題らしいです。

github.com

手動でdtoを作成します。

src/dto/cat/cat.dto.ts
export class CreateCatDto {
    readonly name: string;
    readonly age: number;
    readonly breed: string;
}

カスタムパイプをコントローラにバインドします。

src/cats/cats.controller.ts
import { Body, Controller, Get, Post, UsePipes } from '@nestjs/common';
import { CreateCatDto } from 'src/dto/cat/cat.dto';
import { JoiValidationPipe } from '../pipe/joi-validation/joi-validation.pipe';
import { createCatSchema } from '../schema/cat/cat.schema';
import { Cat } from './cats.interface';
import { CatsService } from './cats.service';

@Controller('cats')
export class CatsController {
    constructor(private catsService: CatsService) {}
    
    @Post()
    @UsePipes(new JoiValidationPipe(createCatSchema))
    create(@Body() createCatDto: CreateCatDto) {
        this.catsService.create(createCatDto);
    }
    @Get()
    findAll(): Cat[] {
        return this.catsService.findAll();
    }
}

UsePipesでバインドできます。

まとめ

ここまでで、

  • Joiを利用したオブジェクトスキーマを検証するパイプについて

を学びました。

次は、パイプについてもっと掘り下げようと思います。

コード

今回のコードは、以下に格納しました。

github.com

takasehiromichiex.com