前回
オブジェクトスキーマを検証するパイプ
バリデーションの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の問題らしいです。
手動で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を利用したオブジェクトスキーマを検証するパイプについて
を学びました。
次は、パイプについてもっと掘り下げようと思います。
コード
今回のコードは、以下に格納しました。