如何在 Nestjs 中使用 ConfigModule 设置迁移

问题描述 投票:0回答:1

我正在尝试找出一种在 Nestjs 中使用 typeOrm 0.3.12 和 ConfigModule 设置迁移的方法。该项目中使用的数据库是 Postgres。我有两个问题:

  1. 当尝试生成迁移时,我会收到消息“未发现数据库架构中的任何更改”。当我像这样在实体字段中使用 glob 模式时会发生这种情况:['dist/**/*.entity.js'],而当我对它们进行硬编码时,它工作正常。
  2. 在设置 TypeOrmModule 时找不到从配置加载变量的方法,因为我无法访问模块外部的 ConfigService,但仍然需要一个 ormconfig 文件,我在其中导出数据源,因为迁移脚本需要它。

我在每种情况下尝试的内容:

  1. 首先,我尝试在没有 ConfigModule 的情况下设置迁移,以确保这部分独立正常工作。在这种情况下,我无法通过 glob 模式路径读取实体,我必须将它们一一键入。我运行脚本“typeorm schema:log”,它返回数据库已经是最新的(我正在检查它,但它是空的)。 我的实体如下:
import { Entity, PrimaryGeneratedColumn, Column} from 'typeorm';

@Entity()
export class DoctorEntity {
    @PrimaryGeneratedColumn()
    id:number;

    @Column()
    fullname: string;
}

我在它的相应模块中这样导入:

@Module({
  imports: [TypeOrmModule.forFeature([DoctorEntity])],
  controllers: [DoctorsController],
  providers: [DoctorsService]
})
export class DoctorsModule {}

我的应用程序模块如下:

@Module({
  imports: [ConfigModule.forRoot({
    isGlobal: true,
    envFilePath: `.env.${process.env.NODE_ENV}`
  }),
     TypeOrmModule.forRoot(config),
     DoctorsModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

我使用的配置位于项目的 src 目录中名为 ormconfig.ts 的文件中,我还在其中创建和导出默认数据源,因为迁移脚本需要它。请注意,我在实体领域尝试了许多不同的方法,例如

__dirname+'/**/*.entity{.ts,.js}'
但没有运气。 ormconfig 如下:

export const config : DataSourceOptions = {
    type:"postgres",
    host: "localhost",
    port: 5432,
    username: "test",
    password: "123",
    database: "test",
    entities: ['dist/**/*.entity.js'],
    synchronize: false,
    migrations: ['./migrations/*.js']
}
const dataSource = new DataSource(config);
export default dataSource;

在我的 packages.json 中,我有以下关于迁移的脚本:

"typeorm": "nest build && typeorm-ts-node-commonjs -d ./dist/ormconfig.js",
"migration:generate": "npm run typeorm migration:generate",
"schema:log": "npm run typeorm schema:log"

如果我将 DoctorEntity 直接放在 ormconfig 的实体字段中,它工作正常但是当我使用 glob 模式时,我总是会收到以下错误:

No changes in database schema were found - cannot generate a migration. To create a new empty migration use "typeorm migration:create" command

  1. 为了运行迁移脚本,我需要在脚本中提供数据源路径作为 -d 参数,如上面的 package.json 所示,这意味着我需要从某个文件导出该数据源。但与此同时,为了在 AppModule 导入中设置 TypeOrmModule 时使用 ConfigModule,我需要使用 forRootAsync 函数,如下所示:
TypeOrmModule.forRootAsync({
  imports: [ConfigModule],
  useFactory: (configService: ConfigService) => ({
    type: 'mysql',
    host: configService.get('HOST'),
    port: +configService.get('PORT'),
    username: configService.get('USERNAME'),
    password: configService.get('PASSWORD'),
    database: configService.get('DATABASE'),
    entities: [],
    synchronize: true,
  }),
  inject: [ConfigService],
});

我仍然需要 ormconfig.ts,虽然我从中导出迁移脚本所需的数据源,但我无权访问那里的 ConfigService,我感觉有点迷茫...... 我花了 3 天时间寻找问题的解决方案,但没有运气。因此,我认为只传递硬编码的实体是“可以”的,但是当我尝试继续时,我偶然发现了第二个问题。任何帮助将不胜感激。谢谢!

nestjs typeorm database-migration nestjs-config nestjs-typeorm
1个回答
0
投票

关于问题的第一部分,我遇到了this github issue for typeorm 0.3.12 sprecifically。看来 0.3.12 版本正在使用导致问题的 glob 库版本。

The problem only exists on Windows
.修复方法:
As of current date, downgrading typeorm to version 0.3.11 solves the problem of not being able to load entities with glob pattern path
。由于 github 上有一个未解决的问题,我想这将在下一个版本中修复。

更新: 关于问题的second部分,确实没有优雅的方法可以做到。数据库连接选项必须通过 TypeOrmModule.forRootAsync 传递,如下所示:

TypeOrmModule.forRootAsync({
  imports: [ConfigModule],
  useFactory: (configService: ConfigService) => ({
    type: 'mysql',
    host: configService.get('HOST'),
    port: +configService.get('PORT'),
    username: configService.get('USERNAME'),
    password: configService.get('PASSWORD'),
    database: configService.get('DATABASE'),
    entities: [],
    synchronize: true,
  }),
  inject: [ConfigService],
});

同时应该存在一个单独的配置文件,它将实例化一个

DataSource
并将其导出为默认值,以便迁移脚本可以工作。为了从 env 文件加载变量 - 直接使用
dotenv
库,我们将打开文件并使用
fs
读取它,然后手动将它们传递给
DataSourceOptions
对象。 像下面这样的东西:

import * as dotenv from 'dotenv';
import * as fs from 'fs';

const data: any = dotenv.parse(fs.readFileSync(`${environment}.env`));

export const config : DataSourceOptions = {
    type:"postgres",
    host: data.HOST,
    port: data.PORT,
    username: data.USERNAME,
    password: data.PASSWORD,
    database: data.DATABASE,
    entities: ['dist/**/*.entity.js'],
    synchronize: false,
    migrations: ['./migrations/*.js']
}

export default new DataSource(config);

© www.soinside.com 2019 - 2024. All rights reserved.