Reputation: 31
Trying to integrate migrations in a nest.js project I ran the migration:create command from typeorm and there was no problem, but when I try to generate a migration with migration:generate like this: yarn run typeorm migration:generate ./src/migrations -d ./src/database/database.provider.ts
being ./src/migrations the folder where I want the migrations to be and ./src/database/database.provider.ts where I have my Datasource as I will show you in a moment, the point is that I got the following error:
`
Error: Given data source file must contain export of a DataSource instance
at Function.loadDataSource (C:\Proyectos\AmazingDigisignBackend\documents-service-nest\node_modules\src\commands\CommandUtils.ts:49:19)
at async Object.handler (C:\Proyectos\AmazingDigisignBackend\documents-service-nest\node_modules\src\commands\MigrationGenerateCommand.ts:73:26)
Done in 3.74s.
this is database.provider.ts:
import {DynamicModule} from "@nestjs/common";
import {ConfigService} from "@nestjs/config";
import {TypeOrmModule} from "@nestjs/typeorm";
import {DataSourceOptions} from "typeorm";
export const DatabaseProvider: DynamicModule = TypeOrmModule.forRootAsync({
inject: [ConfigService],
async useFactory(config: ConfigService) {
return {
type: 'postgres',
host: config.get('DATABASE_HOST'),
username: config.get('DATABASE_USERNAME'),
password: config.get('DATABASE_PASSWORD'),
port: config.get('DATABASE_PORT'),
database: config.get('DATABASE_NAME'),
autoLoadEntities: true,
synchronize: false,
migrations: [__dirname + '/../src/migrations/*{.ts,.js}'],
} as DataSourceOptions;
}
})
and this is my database module:
import {Module} from '@nestjs/common';
import {DatabaseProvider} from './database.provider';
@Module({
imports: [DatabaseProvider],
exports: [DatabaseProvider]
})
export class DatabaseModule {
};
I have tried to use the old typeorm commands like:yarn run typeorm migration:generate -n newMigration
.
I have checked the documentation like a hundred times and nowhere do they tell you how to generate a migration using the typeormmoduleconfig as datasource, I was thinking of creating an ormconfig.json but I don't like it, if nothing else works I guess I wouldn't have much choice.
Upvotes: 3
Views: 1768
Reputation: 89
In times of this, we revert back to node ;-) Its much better to use dotenv. try this Make a database module Add this provider database.provider.ts
import { registerAs } from "@nestjs/config";
import { config as dotenvConfig } from 'dotenv';
import { DataSource, DataSourceOptions } from "typeorm";
dotenvConfig({ path: '.env.dev' });
const config = {
type: 'postgres',
host: `${process.env.POSTGRES_HOST}`,
port: `${process.env.POSTGRES_PORT}`,
username: `${process.env.POSTGRES_USER}`,
password: `${process.env.POSTGRES_PASSWORD}`,
database: `${process.env.POSTGRES_DB}`,
entities: ["dist/**/*.entity{.ts,.js}"],
migrations: ["dist/migrations/*{.ts,.js}"],
autoLoadEntities: true,
synchronize: false,
}
export default registerAs('typeorm', () => config)
export const connectionSource = new DataSource(config as DataSourceOptions);
And for your database module
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import typeorm from './database.provider';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true, load: [typeorm]
}), // Make ConfigModule global
TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: async (configService: ConfigService) => (configService.get('typeorm'))
}),
],
})
export class DatabaseModule { }
Add this to package json
"typeorm": "ts-node ./node_modules/typeorm/cli",
"migration:run": "npm run typeorm migration:run -- -d ./src/database/database.provider.ts",
"migration:generate": "npm run typeorm -- -d ./src/config/database.provider.ts migration:generate ./src/migrations/$npm_config_name",
"migration:create": "npm run typeorm -- migration:create ./src/migrations/$npm_config_name",
"migration:revert": "npm run typeorm -- -d ./src/database/database.provider.ts migration:revert"
Upvotes: 0
Reputation: 318
The file database.provider.ts
that you are providing to the command yarn run typeorm migration:generate
exports a NestJS dynamic module, not a DataSource that can be used by the TypeORM CLI.
However, you could add a function that build the DataSource options in database.provider.ts
, and then reuse this function in a separate file to build the CLI's required configuration.
In your database.provider.ts :
import {DynamicModule} from "@nestjs/common";
import {ConfigService} from "@nestjs/config";
import {TypeOrmModule} from "@nestjs/typeorm";
import {DataSourceOptions} from "typeorm";
export const DatabaseProvider: DynamicModule = TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: buildDataSourceOptions
})
export function buildDataSourceOptions(configService: ConfigService): DataSourceOptions {
return {
type: 'postgres',
host: config.get('DATABASE_HOST'),
username: config.get('DATABASE_USERNAME'),
password: config.get('DATABASE_PASSWORD'),
port: config.get('DATABASE_PORT'),
database: config.get('DATABASE_NAME'),
autoLoadEntities: true,
synchronize: false,
migrations: [__dirname + '/../src/migrations/*{.ts,.js}'],
};
}
and the configuration file for TypeORM cli, in a separate file (database.config.ts
for example)
import { ConfigModule, ConfigService } from '@nestjs/config';
import { DataSource } from 'typeorm';
import { buildDataSourceOptions } from './database.provider';
// This will load environment values.
ConfigModule.forRoot(/* Pass here the same options that you would pass when
calling this method from your root module */);
// This will be used by the cli
export default new DataSource(buildDataSourceOptions(new ConfigService()));
Therefore, you could call the CLI this way :
yarn run typeorm migration:generate ./src/migrations -d ./src/database/database.config.ts
Also, the option autoLoadEntities
is not supported by the TypeORM CLI. You could replace this option by something like this entities: ['dist/**/*.entity{.ts,.js}']
Upvotes: 0