Kirill Vasilkovich
Kirill Vasilkovich

Reputation: 43

Nest.js + TypeORM. TypeORM didn't see .env file

I have some issue about typeorm migrations. I have typeorm config (see below).

data-source.ts:

import { DataSource, DataSourceOptions } from 'typeorm';

export const dataSourceOptions: DataSourceOptions = {
  type: 'postgres',
  host: process.env.POSTGRES_HOST,
  port: +process.env.POSTGRES_PORT,
  username: process.env.POSTGRES_USERNAME,
  password: process.env.POSTGRES_PASSWORD,
  database: process.env.POSTGRES_DATABASE,
  entities: ['dist/**/*.entity.js'],
  migrations: ['dist/db/migrations/*.js'],
  synchronize: true,
};

const dataSource = new DataSource(dataSourceOptions);
export default dataSource;

And when I'm trying to start migrations, typeorm throws an error (but if I replace process.env with normal string, it works).

I attached scripts from package.json

"build": "nest build",
"start": "cross-env NODE_ENV=production nest start",
"start:dev": "cross-env NODE_ENV=development nest start --watch",
"typeorm": "npm run build && npx typeorm -d dist/db/data-source.js",
"migration:generate": "npm run typeorm -- migration:generate",
"migration:run": "npm run typeorm -- migration:run",
"migration:down": "npm run typeorm -- migration:revert"

I need the config to see data from env during migrations.

Maybe this is caused by the fact that I use cross env. And I read it like this

App.module.ts:

@Module({
  imports: [
...
    ConfigModule.forRoot({
      envFilePath: `.${process.env.NODE_ENV}.env`,
    }),
  ],
...
  controllers: [],
  providers: [],
})
export class AppModule {}

Anyway,I hope for your help

Upvotes: 4

Views: 2495

Answers (2)

anand
anand

Reputation: 381

To deal with commandline migrations, you can use an additional typeorm.config.ts file on the root directory.

import { DataSource, DataSourceOptions } from 'typeorm';
import { config } from 'dotenv';
import { resolve } from 'path';

config({ path: resolve(__dirname, '.env') });

const DataSourceConfig = new DataSource({
  type: 'mysql',
  host: process.env.TYPEORM_HOST,
  port: Number(process.env.TYPEORM_PORT),
  username: process.env.TYPEORM_USERNAME,
  password: process.env.TYPEORM_PASSWORD,
  database: process.env.TYPEORM_DATABASE,
  migrations: ['./database/migrations/*'],
  synchronize: false,
  extra: {
    charset: 'utf8mb4',
  },
  migrationsTableName: 'migrations',
});

export default DataSourceConfig;


And to use typeorm inside NestJS app, create a typeorm.service.js file.

import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from '@nestjs/typeorm';

@Injectable()
export class TypeOrmConfigService implements TypeOrmOptionsFactory {
  constructor(private configService: ConfigService) {}

  public createTypeOrmOptions(): TypeOrmModuleOptions {
    return {
      type: 'mysql',
      host: this.configService.get<string>('TYPEORM_HOST'),
      port: this.configService.get<number>('TYPEORM_PORT'),
      username: this.configService.get<string>('TYPEORM_USERNAME'),
      password: this.configService.get<string>('TYPEORM_PASSWORD'),
      database: this.configService.get<string>('TYPEORM_DATABASE'),
      autoLoadEntities: true,
    };
  }
}

And load this service in app.module.ts file

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    TypeOrmModule.forRootAsync({ useClass: TypeOrmConfigService }),
  ]
});
export class AppModule {}

And then inside package.json file, define the commands. Note that I'm using the typeorm-ts-node-commonjs package because my typeorm.config.js file is in Typescript.

"migration:run": "typeorm-ts-node-commonjs -d typeorm.config.ts migration:run",
"migration:create": "cd database/migrations && typeorm-ts-node-commonjs migration:create",
"migration:revert": "typeorm-ts-node-commonjs -d typeorm.config.ts migration:revert"

Upvotes: 4

Micael Levi
Micael Levi

Reputation: 6685

when running typeorm migrations, nestjs doesn't come into play. It's only typeorm. This should be clear as you're using TypeORM CLI (the command npx typeorm ...), and TypeORM has no clue that it is being used with NestJS.

So that code where you have ConfigModule.forRoot isn't called. That's why your .env didn't has read

One way to solve that is by using dotenv (the lib that @nestjs/config uses under the hood to read .env files into process.env object) directly. Follow their docs: https://npmjs.com/dotenv

Upvotes: 8

Related Questions