NestJS相关配置

环境配置


参考文档地址
在 Node.js 应用程序中,通常使用.env文件来表示每个环境,这些文件包含键值对,每个键代表一个特定值。在不同的环境中运行应用程序只需交换正确的文件即可.env。

安装所需的依赖项

yarn add @nestjs/config -D
@@filename(app.module)
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';

@Module({
  imports: [ConfigModule.forRoot()],
})
export class AppModule {}

上述代码将从.env默认位置(项目根目录)加载并解析文件
示例.env文件如下所示:

DATABASE_USER=test
DATABASE_PASSWORD=test

自定义环境文件

默认情况下,包会.env在应用程序的根目录中查找文件。要为文件指定其他路径.env,请设置envFilePath传递给 的(可选)选项对象的属性forRoot(),如下所示:

ConfigModule.forRoot({
  envFilePath: '.development.env',
});

可以为.env文件指定多个路径,如下所示:

ConfigModule.forRoot({
  envFilePath: ['.env.development.local', '.env.development'],
});

Tip: 如果在多个文件中发现一个变量,则第一个变量优先。

使用模块

ConfigModule.forRoot({
	// 声明为全局模块,在其他模块中可以直接使用无需引入了
	isGlobal: true,
});

自定义配置文件

自定义配置文件来返回嵌套的配置对象

@@filename(config/configuration.ts)
export default () => ({
  port: parseInt(process.env.PORT, 10) || 3000,
  database: {
    host: process.env.DATABASE_HOST,
    port: parseInt(process.env.DATABASE_PORT, 10) || 5432
  }
});

使用传递给方法的选项对象的属性load来加载此文件

import configuration from './config/configuration';

@Module({
  imports: [
    ConfigModule.forRoot({
      load: [configuration],
    }),
  ],
})
export class AppModule {}

使用ConfigService

引入ConfigModule

@@filename(feature.module.ts)
@Module({
  imports: [ConfigModule],
  // ...
})

使用标准构造函数注入来注入

constructor(private configService: ConfigService) {}

使用

// 以环境方式获取
const dbUser = this.configService.get<string>('DATABASE_USER');

// 自定义配置文件方式获取
const dbHost = this.configService.get<string>('database.host');

配置 Typeorm + Mysql


Typeorm中文文档
Typeorm英文文档
&
Mysql官网地址

# 安装typeorm 和 mysql
yarn add typeorm mysql2
yarn add -D @nestjs/typeorm

安装过程完成后,我们可以将其导入TypeOrmModule根目录AppModule

@@filename(app.module)
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: '123456',
      database: 'test_project',
      entities: [ 'dist/**/*.entity{.ts,.js}' ],
      // 重试连接的延迟时间(ms)默认值:3000
      retryDelay: 500,
      // 重试连接次数默认值:10
      retryAttempts: 10,
      // 如果为true,实体将自动加载
      autoLoadEntities: true,
      // 是否应在每次启动应用程序时自动创建数据库架构。请谨慎使用此选项,不要在生产环境中使用 - 否则可能会丢失生产数据
      synchronize: true,
    }),
  ],
})
export class AppModule {}

配合ConfigModule

import { Module } from '@nestjs/common'
import { AppController } from './app.controller'
import { AppService } from './app.service'
import { TypeOrmModule } from '@nestjs/typeorm'
import { ConfigModule, ConfigService } from '@nestjs/config'

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: '.env'
    }),
    TypeOrmModule.forRootAsync({
      // @ts-ignore
      useFactory: async (config: ConfigService) => ({
        type: config.get('DATABASE_TYPE'),
        host: config.get('DATABASE_HOST'),
        port: config.get('DATABASE_PORT'),
        username: config.get('DATABASE_USERNAME'),
        password: config.get('DATABASE_PASSWORD'),
        database: config.get('DATABASE_NAME'),
        entities: [ __dirname + '/**/*.entity{.ts,.js}' ],
        synchronize: true,
        retryDelay: 1000,
        retryAttempts: 10
      }),
      inject: [ ConfigService ],
    })
  ],
  controllers: [ AppController ],
  providers: [ AppService ],
})
export class AppModule {}

验证器

参考地址

yarn add class-validator class-transformer

自定义验证规则管道

创建文件

nest g pi pipe/validation-pipe
@@filename(pipe/validation-pipe.pipe)

import { ArgumentMetadata, BadRequestException, Injectable, PipeTransform } from '@nestjs/common'
import { plainToInstance } from 'class-transformer'
import { validate } from 'class-validator'

@Injectable()
export class ValidationPipe implements PipeTransform {
  async transform(value: any, metadata : ArgumentMetadata) {
    const metaType = metadata.metatype
    if (!metaType || !this.toValidate(metaType)) {
      // 如果没有传入验证规则,则不验证,直接返回数据
      return value
    }
    // 将对象转换为 Class 来验证
    const object = plainToInstance(metaType, value)
    const errors = await validate(object)
    if (errors.length > 0) {
      // 取第一个错误信息并返回
      const msg = Object.values(errors[0].constraints)[0]
      throw new BadRequestException(msg)
    }
    return value
  }
  private toValidate(metaType: unknown): boolean {
    const types: unknown[] = [ String, Boolean, Number, Array, Object ]
    return !types.includes(metaType)
  }
}

引入管道

import { NestFactory } from '@nestjs/core'
import { AppModule } from './app.module'
import { ValidationPipe } from '../pipe/validation-pipe/validation-pipe.pipe'

async function bootstrap() {
  const app = await NestFactory.create(AppModule)

  app.useGlobalPipes(new ValidationPipe())

  await app.listen(3000)
}
bootstrap()

验证

@@filename(user/user.module.ts)
...
@Post()
create(@Body() createUserDto: CreateUserDto) {
  return this.userService.create(createUserDto)
}
...

@@filename(user/dto/create-user.dto.ts)
import { IsEmail, IsNotEmpty } from 'class-validator'

export class CreateUserDto {
  @IsEmail({
	message: '邮箱格式不正确'	
  })
  email: string;

  @IsNotEmpty({
	message: '密码不能为空'
  })
  password: string;
}

拓展

Param参数中使用
...
@Get(':id')
findOne(@Param() params: FindOneParams) {
  return 'This action returns a user';
}
...

--------------------------------------------------

import { IsNumberString } from 'class-validator';

export class FindOneParams {
  @IsNumberString()
  id: number;
}
禁用详细错误
app.useGlobalPipes(
  new ValidationPipe({
    disableErrorMessages: true,
  })
)
白名单
app.useGlobalPipes(
  new ValidationPipe({
    // 删除掉未在dto管道中声明的属性
    whitelist: true,
    // 返回参数异常错误响应
    forbidNonWhitelisted: true
  })
)
类型转换

默认情况下,每个路径参数和查询参数都以String的类型传输

# 局部使用
@@filename(cats.controller.ts)
@Post()
@UsePipes(new ValidationPipe({ transform: true }))
async create(@Body() createCatDto: CreateCatDto) {
  this.catsService.create(createCatDto);
}

# 全局配置
app.useGlobalPipes(
  new ValidationPipe({
    transform: true,
  })
)
----------
# 在局部使用或者全局配置后,参数将会进行类型转换
@Get(':id')
findOne(@Param('id') id: number) {
  console.log(typeof id === 'number'); // true
  return 'This action returns a user';
}
明确值转换

ParseIntPipe | ParseBoolPipe | ParseStringPipe

import { ParseIntPipe, ParseBoolPipe } from '@nestjs/common'

...
@Get(':id')
findOne(
  @Param('id', ParseIntPipe) id: number,
  @Query('sort', ParseBoolPipe) sort: boolean,
) {
  console.log(typeof id === 'number'); // true
  console.log(typeof sort === 'boolean'); // true
  return 'This action returns a user';
}
...
映射类型(构建输入验证类型)

PartialType()将所有的参数设置为可选

import { PartialType } from '@nestjs/mapped-types'

export class CreateCatDto {
  name: string;
  age: number;
  breed: string;
}
export class UpdateCatDto extends PartialType(CreateCatDto) {}

// UpdateCatDto: 
// 		name?: string;
//		age?: number;
//		breed?: string;

PickType()函数通过从输入类型中选择一组属性来构造新类型(类)

import { PickType } from '@nestjs/mapped-types'

export class CreateCatDto {
  name: string;
  age: number;
  breed: string;
}
export class UpdateCatAgeDto extends PickType(CreateCatDto, ['age'] as const) {}

OmitType()函数通过从输入类型中选取所有属性,然后删除一组特定的键来构造类型

import { OmitType } from '@nestjs/mapped-types'

export class CreateCatDto {
  name: string;
  age: number;
  breed: string;
}

export class UpdateCatDto extends OmitType(CreateCatDto, ['name'] as const) {}

IntersectionType()函数将两种类型组合成一种新类型(类)

import { IntersectionType } from '@nestjs/mapped-types'

export class CreateCatDto {
  name: string;
  breed: string;
}

export class AdditionalCatInfo {
  color: string;
}

export class UpdateCatDto extends IntersectionType(
  CreateCatDto,
  AdditionalCatInfo,
) {}

类型映射实用函数是可组合的

export class UpdateCatDto extends PartialType(
  OmitType(CreateCatDto, ['name'] as const),
) {}

验证数组

@Post()
createBulk(
  @Body(new ParseArrayPipe({ items: CreateUserDto }))
  createUserDtos: CreateUserDto[],
) {
  return 'This action adds new users';
}

当参数格式为GET /?ids=1,2,3时,进行验证并处理

@Get()
findByIds(
  @Query('ids', new ParseArrayPipe({ items: Number, separator: ',' }))
  ids: number[],
) {
  return 'This action returns users by ids';
}
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林_深时见鹿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值