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

Jay*_*Jay 1 migration typeorm nestjs dotenv nestjs-config

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

斗争是这样的 - 我的迁移脚本需要读取立即返回的对象 -

{
  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
}
Run Code Online (Sandbox Code Playgroud)

但是,当我使用 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(),
    };
  }
}
Run Code Online (Sandbox Code Playgroud)

我已经告诉 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() 来获取对象。否则它将隐藏在DatabaseConfiguration类内部、函数内部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,它正在寻找作为对象的连接connection.options,在该对象中它可以选择type创建正确的驱动程序)-

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);
        ...
       }
    }
};
Run Code Online (Sandbox Code Playgroud)

我的type没有被定义。

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

Jay*_*Jay 10

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

首先,让我们解决使用 NestJs、dotenv 和配置文件运行数据库的基本设置。显然我们已经放弃了不支持.env.

应用程序模块.ts

imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    TypeOrmModule.forRootAsync({
      useClass: DatabaseConfiguration,
    }),
    ...
]
Run Code Online (Sandbox Code Playgroud)

数据库.配置.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(),
    };
  }
}
Run Code Online (Sandbox Code Playgroud)

.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"
Run Code Online (Sandbox Code Playgroud)

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

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

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

迁移.configuration.ts

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

export default (new DatabaseConfiguration()).createTypeOrmOptions()
Run Code Online (Sandbox Code Playgroud)

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

包.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"
    ...
  },
Run Code Online (Sandbox Code Playgroud)

我在那里留下了一些其他脚本...但这是typeorm重要的,再次查看--config哪个定义了 TypeOrm 配置对象将返回的位置。

  • 我按照这些指示进行操作,效果非常好!直到我尝试运行迁移并得到“缺少必需的参数:dataSource”。我该如何解决这个问题? (3认同)