如何实现 NestJs 配置文件、.env (DOTENV)、TypeOrm 数据库配置和迁移

How to implement NestJs Configuration Files, .env (DOTENV), TypeOrm Database Configuration, AND Migrations

我一直在尝试让我的 TypeOrm 配置与 Migrations 和 .env 一起很好地工作,而无需在两个地方指定它。

困难在于 - 我的迁移脚本需要读取立即返回的 object -

{
  type: 'postgres',
  host: '127.0.0.1',
  port: 5432,
  username: 'postgres',
  password: 'myPassword',
  database: 'postgres',
  entities: [ 'dist/**/*.entity.js' ],
  logging: [ 'query', 'error', 'schema' ],
  synchronize: false,
  migrations: [ 'dist/app/database/migrations/*.js' ],
  cli: { migrationsDir: 'src/app/database/migrations' },
  namingStrategy: SnakeNamingStrategy {
    nestedSetColumnNames: { left: 'nsleft', right: 'nsright' },
    materializedPathColumnName: 'mpath'
  },
  subscribers: [],
  migrationsRun: false,
  dropSchema: false
}

但是当我使用 NestJs 建议的配置同时还使用 .env (DOTENV) 文件时,解决方案如下所示:

import {TypeOrmModuleOptions, TypeOrmOptionsFactory} from "@nestjs/typeorm";
import {SnakeNamingStrategy} from "typeorm-naming-strategies";

export class DatabaseConfiguration implements TypeOrmOptionsFactory {
  createTypeOrmOptions(): TypeOrmModuleOptions | Promise<TypeOrmModuleOptions> {
    return {
      type: "postgres",
      host: process.env.POSTGRES_HOST,
      port: parseInt(process.env.POSTGRES_PORT, 10) || 5432,
      username: process.env.POSTGRES_USERNAME,
      password: process.env.POSTGRES_PASSWORD,
      database: process.env.POSTGRES_DATABASE,

      entities: [process.env.TYPEORM_ENTITIES],
      logging: true,
      synchronize: false,
      migrations: [process.env.TYPEORM_MIGRATIONS],
      cli: {
        migrationsDir: process.env.TYPEORM_MIGRATIONS_DIR,
      },
      namingStrategy: new SnakeNamingStrategy(),
    };
  }
}

我已经告诉 TypeOrm 在我的 package.json 中哪里可以找到配置文件(非常重要),就像这样(参见 --config 标签):

"typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js --config dist/app/config/database.configuration.js"

这意味着我的迁移需要调用 (new DatabaseConfiguration()).createTypeOrmOptions() 得到 object。否则它将隐藏在 DatabaseConfiguration class 中,createTypeOrmOptions 函数中。

这造成了 TypeOrm 错误: MissingDriverError: Wrong driver: "undefined" given. Supported drivers are: "aurora-data-api", "aurora-data-api-pg", "better-sqlite3", "capacitor", "cockroachdb", "cordova", "expo", "mariadb", "mongodb", "mssql", "mysql", "nativescript", "oracle", "postgres", "react-native", "sap", "sqlite", "sqljs"

因为正如您在 node_modules/typeorm/driver/DriverFactory.js 文件中看到的那样,它正在寻找作为 object connection.options 的连接,它可以在其中获取 type创建正确的 driver)-

DriverFactory.prototype.create = function (connection) {
        console.log(connection.options);
        var type = connection.options.type;
        switch (type) {
            case "mysql":
                return new MysqlDriver_1.MysqlDriver(connection);
            case "postgres":
                return new PostgresDriver_1.PostgresDriver(connection);
        ...
       }
    }
};

我的 type 没有定义。

因此,对于那些不想花几个小时调试它的人,请查看下面我的详细设置...如果有帮助,请为我的问题和答案投票,因为我无法在任何地方找到全面的答案.

这是我的设置开始到结束。

首先,让我们解决一个基本设置,仅 运行 使用 NestJs、dotenv 和配置文件连接数据库。显然我们已经远离了不支持 .env.

的 ormconfig.json

app.module.ts

imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    TypeOrmModule.forRootAsync({
      useClass: DatabaseConfiguration,
    }),
    ...
]

database.configuration.ts

import {TypeOrmModuleOptions, TypeOrmOptionsFactory} from "@nestjs/typeorm";
import {SnakeNamingStrategy} from "typeorm-naming-strategies";

export class DatabaseConfiguration implements TypeOrmOptionsFactory {
  createTypeOrmOptions(): TypeOrmModuleOptions | Promise<TypeOrmModuleOptions> {
    return {
      type: "postgres",
      host: process.env.POSTGRES_HOST,
      port: parseInt(process.env.POSTGRES_PORT, 10) || 5432,
      username: process.env.POSTGRES_USERNAME,
      password: process.env.POSTGRES_PASSWORD,
      database: process.env.POSTGRES_DATABASE,

      entities: [process.env.TYPEORM_ENTITIES],
      logging: true,
      synchronize: false,
      migrations: [process.env.TYPEORM_MIGRATIONS],
      cli: {
        migrationsDir: process.env.TYPEORM_MIGRATIONS_DIR,
      },
      namingStrategy: new SnakeNamingStrategy(),
    };
  }
}

.env

POSTGRES_TYPE="postgres"
POSTGRES_HOST=127.0.0.1
POSTGRES_PORT=5432
POSTGRES_USERNAME="postgres"
POSTGRES_PASSWORD="takeMyPassword123"
POSTGRES_DATABASE=postgres

TYPEORM_ENTITIES="dist/**/*.entity.js"
TYPEORM_MIGRATIONS="dist/database/migrations/*.js"
TYPEORM_MIGRATIONS_DIR="src/database/migrations"

这样,您的应用程序应该连接到 postgres 数据库和 运行 TypeOrm 查询。 但是如果你想支持迁移呢?

我们需要在 database.configuration.ts 文件的顶部添加一个小的附加层来提取需要为迁移返回的对象。

所以这是一个新的配置文件:

migration.configuration.ts

import {DatabaseConfiguration} from "./database.configuration";

export default (new DatabaseConfiguration()).createTypeOrmOptions()

然后剩下要做的就是更新我们的 package.json 以查看正在调用我们的 databaseConfig 文件并返回渲染对象的 migration.configuration.ts 文件。

package.json

"scripts": {
    ...
    "typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js --config dist/app/config/migration.configuration.js",
    "make:migration-initial": "npm run build && npm run typeorm migration:generate -- -n initial",
    "migrate": "npm run build && npm run typeorm migration:run",
    "migrate:rollback": "npm run build && npm run typeorm migration:revert",
    "migrate:destroy": "npm run build && npm run typeorm migration:revert && rimraf src/app/database/migrations"
    ...
  },

我把我的其他一些脚本留在了那里...但重要的是 typeorm,请再次参阅 --config,它定义了返回 TypeOrm 配置对象的位置。