最近の公式文書Pipes


Pipes!


基本的にクラスで、PipeTransformerインタフェースを実現します.

パイプは変換、有効性の検証を実行します.
コントローラのroute handlerで作業します.@Paramsセクション
pipeはメソッドが実行される前に実行されます.次の方法では、変換または検証された変数を使用します.
Pipeはexception領域を返し、exceptionを放出するとcontrollerメソッドは機能しません.

Built-in Pipes


ValidationPipe
ParseIntPipe
ParseFloatPipe
ParseBoolPipe
ParseArrayPipe
ParseUUIDPipe
ParseEnumPipe
DefaultValuePipe
たとえばParseIntPipeでは、JSの整数で置き換えることができる場合は置き換え、ない場合は例外を放出します.

Binding Pipes


route handlerメソッドにPipeを登録する方法は、次のとおりです.
@Get(':id')
async findOne(@Param('id', ParseIntPipe) id: number) {
  return this.catsService.findOne(id);
}
同じ方法でいいです.

{
  "statusCode": 400,
  "message": "Validation failed (numeric string is expected)",
  "error": "Bad Request"
}
pipeに異常が発生した場合にこれらを返します.
このときパイプにclassが渡されます.DIの責任をFrameworkに委ね、通過しなければfindOne methodは実行しません.
@Get(':id')
async findOne(
  @Param('id', new ParseIntPipe({ errorHttpStatusCode: HttpStatus.NOT_ACCEPTABLE }))
  id: number,
) {
  return this.catsService.findOne(id);
}
ここではclassではなくインスタンスを渡します.
ParseUUIDPipe()は、UUIDversionが3,4,5であることに依存する.

Custom Pipes

import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common';

@Injectable()
export class ValidationPipe implements PipeTransform {
  transform(value: any, metadata: ArgumentMetadata) {
    return value;
  }
}
簡単な検証パイプ.直接受け取って直接吐き出すパイプ
常にPipeTransformというインタフェースをインポートし、PipeTransformとして作成できます.もしそうなら、Tはinputを決定することができ、Rは戻るタイプを決定することができる.
各Pipeは、メソッドにパラメータをインポートするtransform(value:any,metadata:ArgumentMetadata)という関数を実装します.
メタデータは

export interface ArgumentMetadata {
  type: 'body' | 'query' | 'param' | 'custom';
  metatype?: Type<unknown>;
  data?: string;
}
持つ形.
typeはどこで書かれていますか(@Body、@Param、@Query、@Custom)
metaTypeはタイプのタイプと言えます.
インスタンスに関する情報だけであれば、static methodを呼び出すにはどうすればいいですか?このときtypeofinstanceで元のクラスを受信し、そのクラスのメソッドを呼び出す.単純なインスタンスタイプではなく、インスタンスの親タイプを作成します.
もちろん、vanilla javascriptまたはtypeが宣言されている場合は未定義です.
データは装飾器にあります.@Body(「string」)で「string」を表す
実行時にインタフェースが消え、methodパラメータのタイプがクラスではなくインタフェースとして定義されている場合、methodタイプはobjectと呼ばれます.

Schema Based Validation


ここでDTOが再開...
export class CreateCatDto {
  name: string;
  age: number;
  breed: string;
}
@Post()
async create(@Body() createCatDto: CreateCatDto) {
  this.catsService.create(createCatDto);
}
このように検証できます
このようなDTOが存在する場合にはroute handler法で検証することも可能であるが,検証+route handler機能は単一責任則と呼ばれるSOLIDのS原則を失う.
検証クラスは前に置くことができますが、直接呼び出すと不便になります.middlewawreも可能ですが、すべての場所で同じミドルウェアを作成することはできません.

Object Schema Validation


DRYの原則:Don't Repeat Yourself反復関数は1つもありません.
さまざまな方法の1つは、モードベースの検証です.
JOIで検証する方法npm i joi
import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } 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;
  }
}
コンストラクション関数からObject Schema,schemaをインポートします.validate()関数を使用して検証プロセスを行います.

Binding validation pipes

@Post()
@UsePipes(new JoiValidationPipe(createCatSchema))
async create(@Body() createCatDto: CreateCatDto) {
  this.catsService.create(createCatDto);
}
同じ方法で検証することもできます.Schemaを加えて、それを検証するのは当然の方法です.

Class Validator


これはTSのみ
npm i class-validator class-transformer
import { IsString, IsInt } from 'class-validator';

export class CreateCatDto {
  @IsString()
  name: string;

  @IsInt()
  age: number;

  @IsString()
  breed: string;
}
これはいいです.
では、パイプももちろん変更しなければなりません.
import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
import { validate } from 'class-validator';
import { plainToClass } from 'class-transformer';

@Injectable()
export class ValidationPipe implements PipeTransform<any> {
  async transform(value: any, { metatype }: ArgumentMetadata) {
    if (!metatype || !this.toValidate(metatype)) {
      return value;
    }
    const object = plainToClass(metatype, value);
    const errors = await validate(object);
    if (errors.length > 0) {
      throw new BadRequestException('Validation failed');
    }
    return value;
  }

  private toValidate(metatype: Function): boolean {
    const types: Function[] = [String, Boolean, Number, Array, Object];
    return !types.includes(metatype);
  }
}
metatypeをinstance=>classと見なせば便利です.Instanceを作成しているtypeは何ですか?
transformがasyncを処理できるように、asyncサポートは非常に信頼性が高い.
ArcgumentMetadataをメタタイプにインポートします.追加文をインポートできます