【NestJs】数据库重构

上一篇文章详细了介绍nestjs 配置数据库,有不懂的小伙伴可以先查看上一篇文章【NestJs】使用连接mysql企业级开发规范在继续往下。
今天这一篇文章主要是针对配置数据库的重构,使用代码规范,方便后期维护。
当应用变得复杂 我们需要借用TypeORM CLI 非常方便的调整。

注意:
TypeORM 读取到extensions 结尾的文件
在这里插入图片描述
但是在根目录的文件 不能进行动态的修改,这样的话变量一旦很多的,修改极其麻烦。
在这里插入图片描述
当然 我们选择 ormconfig.ts ,不过因为我们环境不止一个。需要多多个环境校验。

使用 CLI

此 CLI 工具使用 javascript 编写,并在 node 上运行。如果你的实体文件是 TypeScript 编写,则需要在使用 CLI 之前将它们转换为 javascript。如果只使用 javascript,则可以跳过此部分。

全局安装 ts-node:

你可以在项目中设置 ts-node 以简化操作,如下所示:

npm install ts-node --save-dev

在 package.json 中的 scripts 下添加 typeorm 命令

"script" {
    ...
    "typeorm": "typeorm-ts-node-commonjs"
}

注意:
typeorm 该版本使用的是 “typeorm”: “0.3.7” 要是版本不一致 需要查看官方文档最新使用方法。

根目录创建文件ormconfig.ts,我们需要把app.module.ts配置的数据库迁移:

import { User } from './src/user/user.entity';
import { Profile } from './src/user/profile.entity';
import { Logs } from './src/logs/logs.entity';
import { Roles } from './src/roles/roles.entity';
import { TypeOrmModuleOptions } from '@nestjs/typeorm';

export default {
  type: 'mysql',
  host: 'localhost',
  port: 3306,
  username: 'root',
  password: '123456',
  database: 'testdb',
  entities: [User, Profile, Logs, Roles],
  // 同步本地的schema与数据库 -> 初始化的时候去使用
  synchronize: true,
  // logging: process.env.NODE_ENV === 'development',
  logging: false,
} as TypeOrmModuleOptions;

app.module.ts

import { Global, Logger, Module } from '@nestjs/common';
import { UserModule } from './user/user.module';
import { ConfigModule } from '@nestjs/config';
import * as dotenv from 'dotenv';
import * as Joi from 'joi';
import { TypeOrmModule } from '@nestjs/typeorm';

import { LogsModule } from './logs/logs.module';
import { RolesModule } from './roles/roles.module';
import ormconfig from '../ormconfig';

const envFilePath = `.env.${process.env.NODE_ENV || `development`}`;

@Global()
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath,
      load: [() => dotenv.config({ path: '.env' })],
      validationSchema: Joi.object({
        NODE_ENV: Joi.string()
          .valid('development', 'production')
          .default('development'),
        DB_PORT: Joi.number().default(3306),
        DB_HOST: Joi.string().ip(),
        DB_TYPE: Joi.string().valid('mysql', 'postgres'),
        DB_DATABASE: Joi.string().required(),
        DB_USERNAME: Joi.string().required(),
        DB_PASSWORD: Joi.string().required(),
        DB_SYNC: Joi.boolean().default(false),
      }),
    }),
    TypeOrmModule.forRoot(ormconfig),
    UserModule,
    LogsModule,
    RolesModule,
  ],
  controllers: [],
  providers: [Logger],
  exports: [Logger],
})
export class AppModule {}

在这里插入图片描述
到这里 说明连接成功了。

初始化一个新的TypeORM项目

它使用 TypeORM 创建基本项目所需的所有文件:

  • .gitignore
  • package.json
  • README.md
  • tsconfig.json
  • ormconfig.json
  • src/entity/User.ts
  • src/index.ts
    然后你可以运行npm install来安装所有依赖项。 一旦安装了所有依赖项,你需要修改ormconfig.json并插入您自己的数据库设置。 之后,可以通过运行npm start来运行您的应用程序。

要指定使用的特定数据库,可以使用–database:

npx typeorm init --database mysql2

生成文件data-source.ts 文件结构和ormconfig 类似,

import 'reflect-metadata';
import { DataSource } from 'typeorm';
import { User } from './entity/User';

export const AppDataSource = new DataSource({
  synchronize: true,
  logging: false,
  entities: [User],
  migrations: [],
  subscribers: [],
});

也会生成一个entity文件夹,暂时不用 我们可以先删掉,根据文档我们需要使用new DataSource 接下来需要修改 ormconnfig.ts 文件

import { User } from './src/user/user.entity';
import { Profile } from './src/user/profile.entity';
import { Logs } from './src/logs/logs.entity';
import { Roles } from './src/roles/roles.entity';
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
import { DataSource, DataSourceOptions } from 'typeorm';

export const connectionParams = {
  type: 'mysql',
  host: 'localhost',
  port: 3306,
  username: 'root',
  password: '123456',
  database: 'testdb',
  entities: [User, Profile, Logs, Roles],
  // 同步本地的schema与数据库 -> 初始化的时候去使用
  synchronize: true,
  // logging: process.env.NODE_ENV === 'development',
  logging: false,
} as TypeOrmModuleOptions;

export default new DataSource({
  ...connectionParams,
  migrations: ['src/migrations/**'],
} as DataSourceOptions);

测试:
修改index.ts

import AppDataSource from '../ormconfig';
import { User } from './user/user.entity';

AppDataSource.initialize()
  .then(async () => {
    const res = await AppDataSource.manager.find(User);
    console.log(res);
  })
  .catch((error) => console.log(error));

npx ts-node src/index.ts

结果:
在这里插入图片描述
到此 我们已经完成了一半。

我们需要使用ormconfig 对接不同的环境?
通过环境变量读取不用的.env文件, 通过dotENV来解析不同的配置:

import { TypeOrmModuleOptions } from '@nestjs/typeorm';

import { DataSource, DataSourceOptions } from 'typeorm';
import * as fs from 'fs';
import * as dotenv from 'dotenv';
import { ConfigEnum } from './src/enum/config.enum';

// 通过环境变量读取不同的.env文件
function getEnv(env: string): Record<string, unknown> {
  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'}`);
  // configService
  const config = { ...defaultConfig, ...envConfig };

  // 过多的实体 我们就不需要一个一个的导入加载
  const entitiesDir =
    process.env.NODE_ENV === 'test'
      ? [__dirname + '/**/*.entity.ts']
      : [__dirname + '/**/*.entity{.js,.ts}'];

  return {
    type: config[ConfigEnum.DB_TYPE],
    host: config[ConfigEnum.DB_HOST],
    port: config[ConfigEnum.DB_PORT],
    username: config[ConfigEnum.DB_USERNAME],
    password: config[ConfigEnum.DB_PASSWORD],
    database: config[ConfigEnum.DB_DATABASE],
    entities: entitiesDir,
    // 同步本地的schema与数据库 -> 初始化的时候去使用
    synchronize: true,
    // logging: process.env.NODE_ENV === 'development',
    logging: false,
  } as TypeOrmModuleOptions;
}

export const connectionParams = buildConnectionOptions();

export default new DataSource({
  ...connectionParams,
  migrations: ['src/migrations/**'],
  subscribers: [],
} as DataSourceOptions);

app.module.ts Joi 的配置需要修改一下:

import { Global, Logger, Module } from '@nestjs/common';
import { UserModule } from './user/user.module';
import { ConfigModule } from '@nestjs/config';
import * as dotenv from 'dotenv';
import * as Joi from 'joi';
import { TypeOrmModule } from '@nestjs/typeorm';

import { LogsModule } from './logs/logs.module';
import { RolesModule } from './roles/roles.module';

import { connectionParams } from '../ormconfig';

const envFilePath = `.env.${process.env.NODE_ENV || `development`}`;

@Global()
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath,
      load: [() => dotenv.config({ path: '.env' })],
      validationSchema: Joi.object({
        NODE_ENV: Joi.string()
          .valid('development', 'production')
          .default('development'),
        DB_PORT: Joi.number().default(3306),
        // 生产环境和部署环境可能 HOST 一个是ip 一个是网址一样
        DB_HOST: Joi.alternatives().try(
          Joi.string().ip(),
          Joi.string().domain(),
        ),
        DB_TYPE: Joi.string().valid('mysql', 'postgres'),
        DB_DATABASE: Joi.string().required(),
        DB_USERNAME: Joi.string().required(),
        DB_PASSWORD: Joi.string().required(),
        DB_SYNC: Joi.boolean().default(false),
        LOG_ON: Joi.boolean(),
        LOG_LEVEL: Joi.string(),
      }),
    }),
    TypeOrmModule.forRoot(connectionParams),
    UserModule,
    LogsModule,
    RolesModule,
  ],
  controllers: [],
  providers: [Logger],
  exports: [Logger],
})
export class AppModule {}

最后就是package.json 中 按照官方文档修改的配置:

"scripts": {
      "prebuild": "rimraf dist",
      "build": "cross-env NODE_ENV=production nest build",
      "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
      "start": "ts-node src/index.ts",
      "start:dev": "cross-env NODE_ENV=development nest start --watch",
      "start:debug": "cross-env NODE_ENV=development nest start --debug --watch",
      "start:prod": "cross-env NODE_ENV=production node dist/src/main",
      "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
      "test": "jest",
      "test:watch": "jest --watch",
      "test:cov": "jest --coverage",
      "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
      "test:e2e": "jest --config ./test/jest-e2e.json",
      "typeorm": "typeorm-ts-node-commonjs -d ormconfig.ts",
      "migration:generate": "f() { npm run typeorm migration:generate -p \"./src/migrations/$@\"; }; f",
      "migration:create": "typeorm-ts-node-commonjs migration:create",
      "migration:run": "npm run typeorm migration:run",
      "migration:revert": "npm run typeorm migration:revert",
      "schema:drop": "npm run typeorm schema:drop"
   },

运行代码即可。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

嘴巴嘟嘟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值