配置项
配置项
- 就是把那些数据库配置、端口配置、日志配置、缓存配置、文件上传配置、邮件配置、第三方配置等,这些配置项,统一放到一个文件中,方便管理。
两种方式 1.env 文件 2. yml 配置
安装
pnpm i @nestjs/config -S
pnpm i cross-env -S
pnpm i dotenv -S
根目录
在根目录,不在 src 目录下
- 创建
.env
文件
DATABASE_USER=root
DATABASE_PASSWORD=123456
DATABASE_NAME=testnest1
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATA="EVN或者PRO没用的配置"
- 创建
.env.development
DATABASE_USER=root
DATABASE_PASSWORD=123456
DATABASE_NAME=testnest1
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATA="测试服"
- 创建
.env.production
DATABASE_USER=root
DATABASE_PASSWORD=123456
DATABASE_NAME=testnest1
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATA="正式服"
找到 package.json 文件
"start:dev": "cross-env NODE_ENV=development nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "cross-env NODE_ENV=production node dist/main",
基础版
- 找到根目录 app.module.ts 模块
import { Module } from "@nestjs/common";
import { LoginModule } from "./Login/login.module";
import { UserModule } from "./User/user.module";
// 配置文件
import { ConfigModule } from "@nestjs/config";
import * as dotenv from "dotenv";
const envPath = `.env.${process.env.NODE_ENV || "development"}`;
@Module({
imports: [
UserModule,
LoginModule,
// 修改配置
ConfigModule.forRoot({
isGlobal: true,
envFilePath: envPath,
// 这里新增.env的文件解析
load: [() => dotenv.config({ path: ".env" })],
}),
],
controllers: [],
providers: [],
})
export class AppModule {}
- 使用
import { Inject, Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
@Injectable()
export class LoginService {
constructor() {}
@Inject()
private ConfigService: ConfigService;
async login(): Promise<string> {
return this.ConfigService.get("DATABASE_USER");
}
}
高级版本
测试用例
import { TypeOrmCrudService } from "@nestjsx/crud-typeorm";
import { Inject, Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import UserEntity from "../model/User.entity";
import { ConfigService } from "@nestjs/config";
@Injectable()
export class UserService extends TypeOrmCrudService<UserEntity> {
constructor(@InjectRepository(UserEntity) repo) {
super(repo);
}
@Inject()
private ConfigService: ConfigService;
async createUser(username: string) {
console.log(this.ConfigService.get("DATABASE_NAME"));
// const user = new UserEntity();
// user.username = username;
// return await this.repo.save(user);
}
}
修改数据库配置
- src 目录下面新建一个 config 文件夹里面 新建一个 orm.config.ts
import { TypeOrmModuleOptions } from "@nestjs/typeorm";
import * as fs from "fs";
import * as dotenv from "dotenv";
import * as path from "path";
// 匹配所有实体
const entitiesDir = [path.join(__dirname, "../**/*.entity{.ts,.js}")];
// 通过环境变量读取不同的.env文件
function getEnv(env: string): Record<string, string> {
if (fs.existsSync(env)) {
return dotenv.parse(fs.readFileSync(env));
}
return {};
}
// 通过dotENV来解析不同的配置
function buildConnectionOptions() {
const defaultConfig = getEnv(".env");
const envConfig = getEnv(`.env.${process.env.NODE_ENV || "development"}`);
const config = {
...defaultConfig,
...envConfig,
};
return {
type: "mysql",
host: config.DATABASE_HOST,
port: config.DATABASE_PORT,
username: config.DATABASE_USER,
password: config.DATABASE_PASSWORD,
database: config.DATABASE_NAME,
entities: entitiesDir,
synchronize: false, //同步本地的schema与数据库 ->初始化的时候使用
logging: ["error"], //日志等级
};
}
export const connectionOptions =
buildConnectionOptions() as TypeOrmModuleOptions;
找到连接数据库的模块文件
xxxx.module.ts
import { Global, Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import User from "./model/User.entity";
import { UserController } from "./controller/user.controller";
import { UserService } from "./service/user.service";
import { ConfigModule } from "@nestjs/config";
import * as dotenv from "dotenv";
// 修改数据库配置
import { connectionOptions } from "../config/orm.config";
const envPath = `.env.${process.env.NODE_ENV || "development"}`;
@Global()
@Module({
imports: [
TypeOrmModule.forRoot(connectionOptions),
TypeOrmModule.forFeature([User]),
// 修改配置
ConfigModule.forRoot({
isGlobal: true,
envFilePath: envPath,
// 这里新增.env的文件解析
load: [() => dotenv.config({ path: ".env" })],
}),
],
controllers: [UserController],
providers: [UserService],
})
export class CoreModule {}
使用 yaml 方式配置
安装依赖
安装 js-yaml 包和类型
npm i js-yaml -S
npm i @types/js-yaml -D
pnpm i @nestjs/config -S
pnpm i cross-env -S
在 src
文件夹下创建一个 config
目录来放各个环境的配置,这里创建 3 个环境 dev/prod/test
── src
│ ├── app.module.ts
│ ├── config
│ │ ├── dev.yml
│ │ ├── index.ts
│ │ ├── prod.yml
│ │ └── test.yml
│ ├── main.ts
│ └── user
│ ├── dto
│ │ ├── create-user.dto.ts
│ │ └── update-user.dto.ts
│ ├── entities
│ │ └── user.entity.ts
│ ├── user.controller.ts
│ ├── user.module.ts
│ └── user.service.ts
├── tsconfig.build.json
└── tsconfig.json
config/index.ts
是动态加载所有配置的入口页,代码如下
import { readFileSync } from "fs";
import * as yaml from "js-yaml";
import { join } from "path";
const configFileNameObj = {
development: "dev",
test: "test",
production: "prod",
};
const env = process.env.NODE_ENV;
export default () => {
return yaml.load(
readFileSync(join(__dirname, `./${configFileNameObj[env]}.yml`), "utf8")
) as Record<string, any>;
};
这里有个需要注意的地方导入 js-yaml
的时候一定要用\* as yaml
或者 require()
不然的话会报错 load
方法不存在,当然你也可以单独导入方法,看你喜好。
还需要注意的是导出必须是个函数,以为配置包的 load
方法只接受函数数组
yml
格式的配置文件比如dev.yml
# 数据库配置
db:
host: localhost
port: 3306
user: root
password: root
database: blog
# Redis配置
redis:
host: localhost
port: 6379
password: root
# JWT配置
jwt:
secret: secret
expiration: 3600
# 普通配置
base:
url: http://localhost:8080
data: devdata
然后在 app.module.ts
中配置导入 yml
配置
import configuration from './config/index';
@Module({
imports: [
ConfigModule.forRoot({
cache: true,
load: [configuration],
isGlobal: true,
}),
],
controllers: [],
providers: [],
})
现在如果启动项目的话,大概率 yml
文件会找不到而报错,此时还需要去配置下 cli
的配置文件 nest-cli.json
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"assets": ["**/*.yml"],
"deleteOutDir": true,
"watchAssets": true
},
"generateOptions": {
"spec": false
}
}
特别注意的就是这个打包配置 compilerOptions
中的 assets
,这个要配置成所有的 yml
文件,这样才能在 dist 中找到配置的配置文件
dist
│ ├── app.module.d.ts
│ ├── app.module.js
│ ├── app.module.js.map
│ ├── config
│ │ ├── dev.yml
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.js.map
│ │ ├── prod.yml
│ │ └── test.yml
接下来还需要去修改一下 npm
的 script
命令,加上环境变量来运行对应的环境配置,先安装一个 cross-env
npm i cross-env -D
然后修改对应环境的脚本命令
"start:dev": "cross-env NODE_ENV=development nest start --watch",
"start:debug": "cross-env NODE_ENV=development nest start --debug --watch",
"start:test": "cross-env NODE_ENV=test node dist/main",
"start:prod": "cross-env NODE_ENV=production node dist/main",
使用配置
使用配置的话,需要导入@nestjs/config
提供的服务来获取配置信息,比如在 user 模块使用配置
因为配置已经设置为全局可用,所以不再需要在 user
模块中导入了,可以直接使用
import { ConfigService } from '@nestjs/config';
@Controller('user')
export class UserController {
constructor(
private readonly userService: UserService,
private configService: ConfigService,
) {}
@Get()
findAll() {
console.log('configService===', this.configService.get('db'));
return this.userService.findAll();
}
这里能打印出对应的配置说明多配置环境可以使用了,这是在控制器里面使用这个配置服务,通过注入的方式
那如果是想在模块文件中使用配置服务怎么办,就拿数据库的配置来举例
@Module({
imports: [
// 数据库
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => {
return {
type: 'mysql',
// 可能不再支持这种方式,entities 将改成接收 实体类的引用
//
// entities: [`${__dirname}/**/*.entity{.ts,.js}`],
autoLoadEntities: true,
keepConnectionAlive: true,
...config.get('db.mysql'),
// cache: {
// type: 'ioredis',
// ...config.get('redis'),
// alwaysEnabled: true,
// duration: 3 * 1000, // 缓存3s
// },
} as TypeOrmModuleOptions;
},
}),
],
controllers: [],
providers: [],
})
由配置的例子可以看出通过一个 useFactory
函数,然后将配置服务作为参数传递进行使用,就可以在模块文件中使用配置信息了
根据现有的数据库自动生成实体
安装
pnpm i typeorm-model-generator
相关参数说明
Usage: typeorm-model-generator -h <host> -d <database> -p [port] -u <user> -x
[password] -e [engine]
Options:
--help Show help [boolean]
--version Show version number [boolean]
-h, --host IP address/Hostname for database server
[default: "127.0.0.1"]
-d, --database Database name(or path for sqlite) [required]
-u, --user Username for database server
-x, --pass Password for database server [default: ""]
-p, --port Port number for database server
-e, --engine Database engine
[choices: "mssql", "postgres", "mysql", "mariadb", "oracle", "sqlite"]
[default: "mssql"]
-o, --output Where to place generated models
[default: "./output"]
-s, --schema Schema name to create model from. Only for mssql
and postgres. You can pass multiple values
separated by comma eg. -s scheme1,scheme2,scheme3
--ssl [boolean] [default: false]
在 package.json 中配置
{
...
"scripts": {
"generator:models": "typeorm-model-generator -h yourHost -p 3306 -d yourDatabase -u username -x password -e mysql -o ./src/entities"
},
...
}
使用
pnpm run generator:models