preface
This is a word that anyone who has ever played Linux will know, for example:
Git’s commit record is displayed as a single line, and the commit profile has the word build
The pipe in NEST is mainly used to intercept and convert the input data type.
It is similar to the concept provided by NG
rendering
In actual combat
In fact, the official tutorial is quite good, both local pipes and global pipes are written, here we use the more general global pipe as an example, try to write more close to the business and more vulgar explanation
The installation
# class-validator: provides very rich type decorators
Class-transformer: convert regular data into classes quickly
# https://www.npmjs.com/package/class-validator
# https://www.npmjs.com/package/class-transformer
yarn add class-validator class-transformer
Copy the code
Seal the input intercept pipe
Usage: nest <command> [options]
Options:
-v, --version Output the current version.
-h, --help Output usage information.
Commands:
new|n [options] [name] Generate Nest application.
build [options] [app] Build Nest application.
start [options] [app] Run Nest application.
info|i Display Nest project details.
update|u [options] Update Nest dependencies.
add [options] <library> Adds support foran external library to your project. generate|g [options] <schematic> [name] [path] Generate a Nest element. Available Schematics, ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ � � � ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ │ name │alias│ description │ application │ application │ Generate a new application workspace │ class │ cl │ Generate a new class │ │ configuration │ config │ Generate a CLI configuration file │ controller │ co │ Generate a controller declaration │ │ Generate a custom decorator │ │ filter │ f │ Generate a filter declaration │ gateway │ ga │ Generate a gateway declaration │ guard │ gu │ Generate a guard declaration │ interceptor │in│ Generate an interceptor declaration │ interface │ interface │ Generate an interface │ middleware │ mi │ Generate a Middleware declaration │ │ module │ mo │ Generate a module declaration │ pipe │ PI │ Generate a pipe declaration │ Provider │ pr │ Generate a provider declaration │ resolver │ r │ Generate a GraphQL resolver declaration │ service │ S │ Generate a service declaration │ library │ lib │ Generate a new library within a monorepo │ sub-app │ app │ Generate a new application within a monorepo │ resource │ res │ Generate a new CRUD resourceCopy the code
Validation.pipe. ts will be generated in SRC /common/ Pipes /
# Root path in nest-cli.json configuration! The default is SRC as the development root
nest n pi common/pipes/validation
Copy the code
Pipeline implementation
// src/pipe/validation.pipe.ts
import {
ArgumentMetadata,
BadRequestException,
Injectable,
PipeTransform,
} from '@nestjs/common';
// plainToClass converts a plain JS object to an instance of the specified class
import { plainToClass } from 'class-transformer';
Validator data can be recognized
import { validate } from 'class-validator';
Injectable();
export class ValidationPipe implements PipeTransform {
// Value is the actual data passed in
// Metatype is metadata, which is what the decorator adds
async transform(value: any, { metatype }: ArgumentMetadata) {
if(! metatype || !this.toValidate(metatype)) {
// If no validation rule is passed in, data is returned without validation
return value;
}
// Convert the object to Class for verification
const object = plainToClass(metatype, value);
// Synchronize block, return check result
const errors = await validate(object);
if (errors.length > 0) {
// Just take the first error message and return it
const msg = Object.values(errors[0].constraints)[0];
// Throw this exception, and the logic will deliver nest's error interception
// To intercept this error for processing, start with filters, as discussed later
throw new BadRequestException('field verification failed:${msg}`);
}
return value;
}
// The purpose of this function is to verify that the type of metadata passed in is normal data in the definition
private toValidate(metatype: any) :boolean {
const types: any[] = [String.Boolean.Number.Array.Object];
return !types.includes(metatype);
}
}
Copy the code
configuration
The main entrance (main. Ts)
import { AppModule } from './app.module';
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from './common/pipes/validataion.pipe';
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
cors: false.logger: false});// Set the global pipe
app.useGlobalPipes(new ValidationPipe());
await app.listen(configService.get('SERVE_LISTENER_PORT'));
}
bootstrap()
Copy the code
DTO annotations
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import {
IsInt,
IsNumberString,
IsOptional,
IsString,
Max,
Min,
} from 'class-validator';
export enum UserRole {
Boss = 'back door',
Admin = 'Administrator',
User = 'Regular user',}export class CreateAppDto {
@ApiProperty({ enum: ['Boss'.'Admin'.'User']})role: UserRole;
@IsOptional(a)@IsString({
message: 'Username must be a string',})@ApiPropertyOptional({
description: 'name',})readonlyname? :string;
@IsInt(a)@Min(10, { message: 'Minimum age 10' })
@Max(130, { message: 'Upper age limit 130' })
@ApiProperty({
description: 'age'.minimum: 0.maximum: 130.required: false,})readonly age: number;
@IsString({
message: 'Hobby must be string',})@ApiPropertyOptional({
description: 'hobby',})readonly hobit: string;
}
export class FindOneParams {
@IsNumberString(a)id: number;
}
Copy the code
Controller
import { Controller, Get, Post, HttpCode, Body, Query } from '@nestjs/common';
import {
ApiCreatedResponse,
ApiHeader,
ApiInternalServerErrorResponse,
ApiOkResponse,
ApiOperation,
ApiParam,
ApiQuery,
ApiResponse,
} from '@nestjs/swagger';
import { CreateAppDto, FindOneParams, UserRole } from './app.dto';
import { AppService } from './app.service';
@Controller(a)export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
@ApiHeader({
name: 'Authorization'.description: 'Auth token',})@ApiCreatedResponse({
description: 'Link was successfully created, which is a description of the 201 state.',})@Post('/post')
@HttpCode(200)
@ApiParam({ name: 'name'.description: 'name'.type: CreateAppDto })
postParams(@Body() param: CreateAppDto): string {
return 'Test parameters' + JSON.stringify(param);
}
@Get('/user')
@ApiOperation({
tags: ['Get user information'].description: 'Get user information'.deprecated: true,})@ApiQuery({ name: 'id'.description: 'user id' })
@ApiResponse({ description: 'Successfully requested back, which is essentially the description of 200.'.status: 200 })
@ApiInternalServerErrorResponse({ description: 'Server exception' })
updateApp(@Query() query: FindOneParams) {
return JSON.stringify(query);
}
@Get('/netease-news/:id')
@ApiOkResponse({ description: 'Successful request returned' })
@ApiQuery({ name: 'id'.description: 'user id'.required: false })
async async(@Body() body) {
const res = await this.appService.getNetEaseNew(
'https://anapioficeandfire.com/api/characters/583',
{ data: body },
);
return res.data;
}
@ApiQuery({ name: 'role'.enum: UserRole })
@ApiOperation({
tags: ['Return role information'].description: 'Return role information',})@Get('/role')
async filterByRole(@Query('role') role: UserRole = UserRole.User) {
returnrole; }}Copy the code
conclusion
Have wrong place please leave a message, will correct in time! Thanks for reading ~