NestJS中useFactory配置TypeORM时如何导出DataSource解决迁移报错
问题描述
基于NestJS框架开发应用,app.module.ts中通过useFactory编写TypeORM异步配置,全局安装TypeORM且迁移文件已生成到配置指定路径,执行迁移命令时提示dataSource未找到。
原有配置代码
import { ConfigModule, ConfigService } from '@nestjs/config'; import { TypeOrmModuleAsyncOptions, TypeOrmModuleOptions, } from '@nestjs/typeorm'; import { DataSource } from 'typeorm'; export const typeOrmAsyncConfig: TypeOrmModuleAsyncOptions = { imports: [ConfigModule], inject: [ConfigService], name: 'nameA', useFactory: (configService: ConfigService) => ({ type: 'postgres', host: configService.get('DB_HOST'), port: parseInt(configService.get('DB_PORT') || '5432'), username: configService.get('DB_USER'), password: configService.get('DB_PASSWORD'), database: configService.get('DB_NAME'), entities: [__dirname + './../**/*.entity{.ts,.js}'], migrations: [__dirname + '/../database/migrations/*{.ts,.js}'], synchronize: false, cli: { entitiesDir: __dirname + './../**/*.entity{.ts,.js}', }, ssl: configService.get('DB_SSL') === 'true', }), }; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true }), TypeOrmModule.forRootAsync(typeOrmAsyncConfig), ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
执行迁移命令报错输出
执行typeorm migration:run返回如下结果:
Runs all pending migrations. Options: -h, --help Show help [boolean] -d, --dataSource Path to the file where your DataSource instance is defined. [required] -t, --transaction Indicates if transaction should be used or not for migration run. Enabled by default. [default: "default"] -v, --version Show version number [boolean] Missing required argument: dataSource
报错原因
TypeORM 0.3及以上版本的CLI执行迁移时,不会加载NestJS的依赖注入容器,写在AppModule里的异步配置仅在NestJS应用启动时生效,CLI运行时无法读取到这些配置,必须显式传入一个可被直接加载的独立DataSource实例文件。
解决步骤
- 第一步:创建独立的DataSource配置文件
在项目中新建src/config/data-source.ts,手动加载环境变量,初始化并导出DataSource实例,配置字段和原有TypeORM配置保持一致:import { DataSource } from 'typeorm'; import { config } from 'dotenv'; // 加载.env文件环境变量,对齐NestJS ConfigModule的加载逻辑 config(); export const AppDataSource = new DataSource({ type: 'postgres', host: process.env.DB_HOST, port: parseInt(process.env.DB_PORT || '5432'), username: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, entities: [__dirname + '/../**/*.entity{.ts,.js}'], migrations: [__dirname + '/../database/migrations/*{.ts,.js}'], synchronize: false, ssl: process.env.DB_SSL === 'true', }); - 第二步:调整NestJS中的TypeORM配置,复用DataSource配置避免两边不一致
修改app.module.ts中的typeOrmAsyncConfig,直接引用上面导出的DataSource配置项,单数据源场景建议移除name: 'nameA'配置避免多数据源冲突,多数据源场景则保证两边name值完全一致:import { AppDataSource } from './config/data-source'; export const typeOrmAsyncConfig: TypeOrmModuleAsyncOptions = { imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => ({ ...AppDataSource.options, // 有需要动态覆盖的配置可以在这里追加 }), }; - 第三步:执行迁移命令时显式传入DataSource文件路径
不推荐直接使用全局安装的typeorm命令执行(无法识别TS语法、容易出现版本不匹配问题),推荐用项目本地依赖的typeorm配合ts-node执行:# 开发环境执行TS格式配置 ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js migration:run -d src/config/data-source.ts # 生产环境执行编译后的JS格式配置 node ./node_modules/typeorm/cli.js migration:run -d dist/config/data-source.js
注意:如果项目配置了tsconfig路径别名,必须加上
-r tsconfig-paths/register参数,否则会出现模块找不到的错误。
内容的提问来源于stack exchange,提问作者juztcode
相关产品推荐
相关产品推荐

