UNPKG

create-chuntianxiaozhu

Version:

春天小猪模板工具

689 lines (536 loc) 14.2 kB
# 控制器 初始化控制器 ```bash nest g controller [控制器名] ``` ## 请求 一个请求包括请求方式,请求头,请求内容,请求参数,响应头,响应内容 ```ts // @Get() // @Post() // @Put() // @Delete() // @Patch() // @Options() // @Head() // @All() import { Controller, Get, Query, Post, Body, Put, Param, Delete, } from '@nestjs/common'; import { CreateCatDto, UpdateCatDto, ListAllEntities } from './dto'; @Controller('cats') export class CatsController { @Post() create(@Body() createCatDto: CreateCatDto) { return 'This action adds a new cat'; } @Get() findAll(@Query() query: ListAllEntities) { return `This action returns all cats (limit: ${query.limit} items)`; } @Get(':id') findOne(@Param('id') id: string) { return `This action returns a #${id} cat`; } @Put(':id') update(@Param('id') id: string, @Body() updateCatDto: UpdateCatDto) { return `This action updates a #${id} cat`; } @Delete(':id') remove(@Param('id') id: string) { return `This action removes a #${id} cat`; } } ``` # 服务 服务负责数据存储和检索 nest g service [模块名] ```ts import { Injectable } from '@nestjs/common'; import { Cat } from './interfaces/cat.interface'; @Injectable() export class CatsService { private readonly cats: Cat[] = []; create(cat: Cat) { this.cats.push(cat); } findAll(): Cat[] { return this.cats; } } // 在控制器中使用 import { Controller, Get, Post, Body } from '@nestjs/common'; import { CreateCatDto } from './dto/create-cat.dto'; import { CatsService } from './cats.service'; import { Cat } from './interfaces/cat.interface'; @Controller('cats') export class CatsController { constructor(private catsService: CatsService) {} @Post() async create(@Body() createCatDto: CreateCatDto) { this.catsService.create(createCatDto); } @Get() async findAll(): Promise<Cat[]> { return this.catsService.findAll(); } } ``` # 模块 每个应用程序至少有一个模块,即根模块 nest g module [模块名] ```ts import { Module } from '@nestjs/common'; import { CatsController } from './cats.controller'; import { CatsService } from './cats.service'; @Module({ controllers: [CatsController], providers: [CatsService], }) export class CatsModule {} ``` @Global 装饰@Global()器使模块具有全局范围 # 中间件 可以在函数或带有@Injectable()装饰器的类中实现自定义 Nest 中间件。类应该实现NestMiddleware接口,而函数没有任何特殊要求。让我们首先使用类方法实现一个简单的中间件功能。 ```ts import { Injectable, NestMiddleware } from '@nestjs/common'; import { Request, Response, NextFunction } from 'express'; @Injectable() export class LoggerMiddleware implements NestMiddleware { use(req: Request, res: Response, next: NextFunction) { console.log('Request...'); next(); } } ``` 注入中间件 ```ts import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common'; import { LoggerMiddleware } from './common/middleware/logger.middleware'; import { CatsModule } from './cats/cats.module'; @Module({ imports: [CatsModule], }) export class AppModule implements NestModule { configure(consumer: MiddlewareConsumer) { consumer.apply(LoggerMiddleware).forRoutes('cats'); } } ``` 或者全局中间件 ```ts app.use(logger); ``` # 异常过滤器 ```ts import { ExceptionFilter, Catch, ArgumentsHost, HttpException, } from '@nestjs/common'; import { Request, Response } from 'express'; @Catch(HttpException) export class HttpExceptionFilter implements ExceptionFilter { catch(exception: HttpException, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const request = ctx.getRequest<Request>(); const status = exception.getStatus(); response.status(status).json({ statusCode: status, timestamp: new Date().toISOString(), path: request.url, }); } } ``` 绑定过滤器 ```ts @Post() @UseFilters(new HttpExceptionFilter()) async create(@Body() createCatDto: CreateCatDto) { throw new ForbiddenException(); } ``` 全局过滤器 ```ts async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalFilters(new HttpExceptionFilter()); await app.listen(3000); } bootstrap(); ``` 扩展 的方法范围和控制器范围的过滤器BaseExceptionFilter不应使用 实例化new。相反,让框架自动实例化它们 ```ts import { Catch, ArgumentsHost } from '@nestjs/common'; import { BaseExceptionFilter } from '@nestjs/core'; @Catch() export class AllExceptionsFilter extends BaseExceptionFilter { catch(exception: unknown, host: ArgumentsHost) { super.catch(exception, host); } } ``` # 管道 转换:将输入数据转换为所需的形式(例如,从字符串到整数) 验证:评估输入数据,如果有效,则简单地通过不变;否则,抛出异常 一个常用的类dto验证器 ```ts // 管道数据验证器 import { ArgumentMetadata, BadRequestException, Injectable, PipeTransform, } from '@nestjs/common'; import { plainToInstance } from 'class-transformer'; import { validate } from 'class-validator'; @Injectable() export class ValidationPipe implements PipeTransform<any> { async transform(value: any, metadata: ArgumentMetadata) { const { metatype } = metadata; if (!metatype || !this.toValidate(metatype)) { return value; } const object = plainToInstance(metatype, value); const errors = await validate(object); if (errors.length > 0) { throw new BadRequestException('参数校验失败'); } return value; } private toValidate(metatype: Function): boolean { const types: Function[] = [String, Boolean, Number, Array, Object]; return !types.includes(metatype); } } // 注册全局管道 app.useGlobalPipes(new ValidationPipe()); // 创建具有校验的dto import { IsNotEmpty, IsString } from 'class-validator'; export class CommonDto { @IsNotEmpty() @IsString() name: string; } ``` # 卫兵 守卫是一个用@Injectable()装饰器注释的类,它实现了CanActivate接口 警卫的职责单一。它们根据运行时存在的某些条件(如权限、角色、ACL 等)确定路由处理程序是否处理给定的请求。这通常称为授权 卫兵在所有中间件之后、任何拦截器或管道之前执行 比如权限验证 ```ts // 定义卫兵 import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; import { Observable } from 'rxjs'; @Injectable() export class AuthGuard implements CanActivate { canActivate( context: ExecutionContext, ): boolean | Promise<boolean> | Observable<boolean> { const request = context.switchToHttp().getRequest(); return !!request; } } // 在控制器中使用卫兵 @UseGuards(new AuthGuard()) // 全局使用卫兵 app.useGlobalGuards(new RolesGuard()); ``` ## 权限元数据 ```ts // 定义接口角色 @Post() @SetMetadata('roles', ['admin']) async create(@Body() createCatDto: CreateCatDto) { this.catsService.create(createCatDto); } // 改进装饰器 import { SetMetadata } from '@nestjs/common'; export const Roles = (...roles: string[]) => SetMetadata('roles', roles); @Post() @Roles('admin') async create(@Body() createCatDto: CreateCatDto) { this.catsService.create(createCatDto); } // 在卫兵中进行鉴权 import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; @Injectable() export class RolesGuard implements CanActivate { constructor(private reflector: Reflector) {} canActivate(context: ExecutionContext): boolean { const roles = this.reflector.get<string[]>('roles', context.getHandler()); if (!roles) { return true; } const request = context.switchToHttp().getRequest(); const user = request.user; return matchRoles(roles, user.roles); } } ``` # 拦截器 @Injectable()拦截器是用装饰器注释并实现接口的类NestInterceptor 拦截器具有一组有用的功能,这些功能受到面向方面编程(AOP) 技术的启发 - 在方法执行之前/之后绑定额外的逻辑 - 转换函数返回的结果 - 转换函数抛出的异常 - 扩展基本功能行为 - 根据特定条件完全覆盖函数(例如,出于缓存目的) # 缓存 ```bash yarn add @nestjs/cache-manager cache-manager ``` ```ts // 在指定模块中使用缓存 import { Module } from '@nestjs/common'; import { CacheModule } from '@nestjs/cache-manager'; import { AppController } from './app.controller'; @Module({ imports: [CacheModule.register()], controllers: [AppController], }) export class AppModule {} // 缓存使用 constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {} ``` # 序列化 用于转换和清理要返回给客户端的数据的规则,例如,密码等敏感数据应始终从响应中排除。 ```ts import { Exclude } from 'class-transformer'; export class UserEntity { id: number; firstName: string; lastName: string; @Exclude() password: string; constructor(partial: Partial<UserEntity>) { Object.assign(this, partial); } } ``` 请注意,我们必须返回该类的一个实例。如果您返回纯 JavaScript 对象,例如 ,{ user: new UserEntity() }则该对象将无法正确序列化。 提供别名 ```ts @Expose() get fullName(): string { return `${this.firstName} ${this.lastName}`; } ``` # 任务调度 ```bash yarn add --save @nestjs/schedule yarn add -D @types/cron ``` ```ts import { Module } from '@nestjs/common'; import { ScheduleModule } from '@nestjs/schedule'; @Module({ imports: [ScheduleModule.forRoot()], }) export class AppModule {} ``` 该.forRoot()调用初始化调度程序并注册应用程序中存在的任何声明性cron 作业、超时和间隔。当生命周期挂钩发生时,就会进行注册onApplicationBootstrap,确保所有模块都已加载并声明任何计划的作业。 示例 ```ts import { Injectable, Logger } from '@nestjs/common'; import { Cron } from '@nestjs/schedule'; @Injectable() export class TasksService { private readonly logger = new Logger(TasksService.name); @Cron('45 * * * * *') handleCron() { this.logger.debug('Called when the current second is 45'); } } ``` # 限流 # 日志 ```ts // 开启日志 const app = await NestFactory.create(AppModule, { logger: ['error', 'warn'], }); await app.listen(3000); @Controller() export class AppController { private readonly logger = new Logger(AppController.name); constructor(private readonly appService: AppService) {} @Get() getHello(): string { return this.appService.getHello(); } @Post('/test') test(@Body() commonDto: CommonDto): string { console.log(commonDto.name); this.logger.warn('测试内容'); return '测试'; } } ``` # cookie cookie解析器 ```bash yarn add cookie-parser yarn add -D @types/cookie-parser ``` 中间件 ```ts import * as cookieParser from 'cookie-parser'; app.use(cookieParser()); ``` 获取cookie ```ts @Get() findAll(@Req() request: Request) { console.log(request.cookies); // or "request.cookies['cookieKey']" // or console.log(request.signedCookies); } ``` 设置cookie ```ts @Get() findAll(@Res({ passthrough: true }) response: Response) { response.cookie('key', 'value') } ``` # 文件上传 ```bash yarn add -D @types/multer ``` ```ts @Post('upload') @UseInterceptors(FileInterceptor('file')) uploadFile(@UploadedFile() file: Express.Multer.File) { console.log(file); } ``` ## 文件验证 ```ts import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common'; @Injectable() export class FileSizeValidationPipe implements PipeTransform { transform(value: any, metadata: ArgumentMetadata) { const oneKb = 1000; return value.size < oneKb; } } ``` # 流媒体文件 有时您可能希望将文件从 REST API 发送回客户端。要使用 Nest 执行此操作,通常您需要执行以下操作。 ```ts @Controller('file') export class FileController { @Get() getFile(@Res() res: Response) { const file = createReadStream(join(process.cwd(), 'package.json')); file.pipe(res); } } ``` # 静态资源 ```bash yarn add hbs ``` 使用了hbs(Handlebars)引擎 ```ts import { NestFactory } from '@nestjs/core'; import { NestExpressApplication } from '@nestjs/platform-express'; import { join } from 'path'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create<NestExpressApplication>(AppModule); app.useStaticAssets(join(__dirname, '..', 'public')); app.setBaseViewsDir(join(__dirname, '..', 'views')); app.setViewEngine('hbs'); await app.listen(3000); } bootstrap(); ``` 模板渲染 ```html <!doctype html> <html> <head> <meta charset="utf-8" /> <title>App</title> </head> <body> {{ message }} </body> </html> ``` 渲染控制层 ```ts import { Get, Controller, Render } from '@nestjs/common'; @Controller() export class AppController { @Get() @Render('index') root() { return { message: 'Hello world!' }; } } ``` # 安全 helmet 增加头安全 # 限流 ```bash yarn add @nestjs/throttler ``` ```ts @Module({ imports: [ ThrottlerModule.forRoot({ ttl: 60, limit: 10, }), ], }) export class AppModule {} ``` 定制 ```ts @SkipThrottle() @Controller('users') export class UsersController {} @SkipThrottle() @Controller('users') export class UsersController { // Rate limiting is applied to this route. @SkipThrottle(false) dontSkip() { return "List users work with Rate limiting."; } // This route will skip rate limiting. doSkip() { return "List users work without Rate limiting."; } } @Throttle(3, 60) @Get() findAll() { return "List users works with custom rate limiting."; } ``` 保护策略 ```ts @Injectable() export class ThrottleIpBodyGuard extends ThrottlerGuard { getTracker(req: Request) { return req.ip + req.body.username; } } ```