Appearance
新建配置服务
安装依赖
shell
npm i -S dotenv
npm i -D @types/dotenv
npm install -S @hapi/joi
npm install -D @types/hapi__joits
// config.service.ts
import * as dotenv from "dotenv"
import * as fs from "fs"
import * as Joi from "@hapi/joi"
const configSchema = {}
export type EnvConfig = Record<string, string>
export class ConfigService {
private readonly envConfig: Record<string, string>
// 配置的合并顺序
// .env.[type].local => .env.[type] => .env
constructor(filePath?: string) {
if (filePath) {
this.envConfig = dotenv.parse(fs.readFileSync(filePath))
} else {
// 读取默认配置 .env
// 读取[type].env 配置
// 读取 local.[type].env配置
let defaultEnvConfig
let typeEnvConfig = {}
let localEnvConfig = {}
try {
defaultEnvConfig = dotenv.parse(fs.readFileSync(".env"))
typeEnvConfig = dotenv.parse(
fs.readFileSync(`${process.env.NODE_ENV}.env`)
)
localEnvConfig = dotenv.parse(
fs.readFileSync(`local.${process.env.NODE_ENV}.env`)
)
} catch (err) {}
if (!defaultEnvConfig) {
throw new Error("默认配置文件未找到!")
}
this.envConfig = Object.assign(
defaultEnvConfig,
typeEnvConfig,
localEnvConfig
)
}
// todo
// this.envConfig = this.validateConfig(this.envConfig);
}
private validateConfig(envConfig: EnvConfig): EnvConfig {
const envVarSchema: Joi.ObjectSchema = Joi.object(configSchema)
const { error, value: validateEnvConfig } = envVarSchema.validate(envConfig)
if (error) {
throw new Error("配置文件验证出错")
}
return validateEnvConfig
}
get(key: string): string {
return this.envConfig[key]
}
}
// config.module.ts
import { Module } from "@nestjs/common"
import { ConfigService } from "./config.service"
@Module({
providers: [
{
provide: ConfigService,
useValue: new ConfigService()
}
],
exports: [ConfigService]
})
export class ConfigModule {}
// .env
PORT = 3000注册到全局模块
mysql typeorm 集成
安装依赖
shell
npm i -S @nestjs/typeorm typeorm mysql
mysql typeorm curd 集成
shell
npm i --save @nestjsx/crud @nestjsx/crud-typeorm class-transformer class-validator默认情况下 module 是单列的,意味着模块中 提供者也是单列
认证
shell
npm install --save @nestjs/passport passport passport-local
npm install --save-dev @types/passport-localJWT 功能
npm i -S @nestjs/jwt passport-jwt
npm i -S @types/passport-jwt请求的执行顺序
客户端请求 ---> 中间件 ---> 守卫 ---> 拦截器之前 ---> 管道 ---> 控制器处理并响应 ---> 拦截器之后 ---> 过滤器
重点:在示例给出了它们的写法,注意全局管道、守卫、过滤器和拦截器,只能 new,全局中间件是纯函数,全局管道、守卫、过滤器和拦截器,中间件都不能依赖注入。中间件模块注册也不能用 new,可以依赖注入。管道、守卫、过滤器和拦截器局部注册可以使用 new 和类名,除了管道以为其他都可以依赖注入。拦截器和守卫可以写成高阶方法来传参,达到定制目的
泛型中&是啥意思
&指的是并集类型, | 指的是交集类型
别人的项目结构
main.ts 入口 main.hmr.ts 热更新入口 app.service.ts APP 服务(选择) app.module.ts APP 模块(根模块,必须) app.controller.ts APP 控制器(选择) app.controller.spec.ts APP 控制器单元测试用例(选择) config 配置模块 core 核心模块(申明过滤器、管道、拦截器、守卫、中间件、全局模块) feature 特性模块(主要业务模块) shared 共享模块(共享 mongodb、redis 封装服务、通用服务) tools
装饰器的集中写法
ts
declare type ClassDecorator = <TFunction extends Function>(
target: TFunction
) => TFunction | void
declare type PropertyDecorator = (
target: Object,
propertyKey: string | symbol
) => void
declare type MethodDecorator = <T>(
target: Object,
propertyKey: string | symbol,
descriptor: TypedPropertyDescriptor<T>
) => TypedPropertyDescriptor<T> | void
declare type ParameterDecorator = (
target: Object,
propertyKey: string | symbol,
parameterIndex: number
) => void动态模块中 service 如何被注册到其他动态模块上
configModule 是个动态模块, 现在需要注册到typeormModule 上面, 最好的方式直接申明全局模块采坑记录
ConfigModule 不能读取 module 目录下的 json 配置文件
开发代码都在 src 里,生成代码在 dist (打包自动编译),typescript 打包只会编译 ts 到 dist 下,静态文件 public 和模板 views 不会移动,所以需要放到根目录下, 同理,配置 json 需要放在根目录下。
管道
安装
npm i -S class-validator class-transformer
直接在 DTO 中装饰器定义
ts
// create-cat.dto.ts
export default CreateCatDto {
@IsString()
readonly name: string;
}配置管道 控制器中使用方法装饰器注入 @UsePipes(new ValidationPipe({transform: true}))
class-validator 装饰器大全
@Length @contains('text')
entity 中定义类型和装饰器相比优先级低
ts
@CreateDateColumn({ comment: '创建时间' })
createdAt: Date
@UpdateDateColumn({ comment: '更新时间' })
updatedAt: boolean // 这样也是可以的, 最后也会被解释成 datetime 类型的