我正在尝试找出一种在 Nestjs 中使用 typeOrm 0.3.12 和 ConfigModule 设置迁移的方法。该项目中使用的数据库是 Postgres。我有两个问题:
我在每种情况下尝试的内容:
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
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 天时间寻找问题的解决方案,但没有运气。因此,我认为只传递硬编码的实体是“可以”的,但是当我尝试继续时,我偶然发现了第二个问题。任何帮助将不胜感激。谢谢!
关于问题的第一部分,我遇到了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);