nestjsdotenvmikro-orm

NestJS/Mikro-ORM Migrations not reading .env with @nestjs/config or dotenv


I have validated my .env file gets loaded, using a console.log(process.env);

However, the following code never gets a value, it always uses the default, fall back.

mikro-orm.config.ts

import { Options } from '@mikro-orm/core';
import * as DotEnv from 'dotenv';

const EnvFilePath: string = `${process.cwd()}/.env`;
DotEnv.config({ path: EnvFilePath });
console.log(process.env);

const MikroOrmConfig: Options = {
    entities: [`${__dirname}/**/*.entity{.ts,.js}`],
    type: 'mysql',
    dbName: process.env.DB_DATABASE || 'db_name',
    user: process.env.DB_USERNAME || 'username',
    password: process.env.DB_PASSWORD || 'password',
    host: process.env.DB_SERVER_HOST || 'localhost',
    port: parseInt( process.env.DB_SERVER_PORT || '3306', 10),
};

export default MikroOrmConfig;

The console output has my settings:

DB_DATABASE: 'my_test_db',
DB_PASSWORD: 'my_test_pwd',
DB_SERVER_HOST: 'localhost',
DB_SERVER_PORT: '3306',
DB_USER: 'my_test_user',

However, when I run the migrations, using the Mikro-ORM, it returns an error from the database

code: 'ER_ACCESS_DENIED_ERROR',
  errno: 1045,
  sqlState: '28000',
  sqlMessage: "Access denied for user 'username'@'localhost' (using password: YES)",

If I change the user: process.env.DB_USERNAME || 'username', to be user: process.env.DB_USERNAME, then the error message references Access denied for user 'root'@'localhost' (using password: YES)

If I try to initialize the NestJS config service manually, the Mikro-ORM does not pick up the environment variables either.

ConfigModule.forRoot({
    isGlobal: true,  // Set to global
    envFilePath: [EnvFilePath]
});

const configService = new ConfigService( { envFilePath: '.env' });
const MikroOrmConfig: Options = {
    entities: [`${__dirname}/**/*.entity{.ts,.js}`],
    type: 'mysql',
    dbName: configService.get<string>('DB_DATABASE') || 'db_name2',
    user: configService.get<string>('DB_USERNAME') || 'username2',
    password: configService.get<string>('DB_PASSWORD') || 'password2',
    host: configService.get<string>('DB_SERVER_HOST') || 'localhost',
    port: parseInt( configService.get('DB_SERVER_PORT') || '3306', 10),
};

With or without setting the module in the mikro-orm.config.ts does not make a difference.

If I change the or options to be the actual names, this does work.

const MikroOrmConfig: Options = {
    entities: [`${__dirname}/**/*.entity{.ts,.js}`],
    type: 'mysql',
    dbName: process.env.DB_DATABASE || 'my_test_user',
    user: process.env.DB_USERNAME || 'my_test_db',
    password: process.env.DB_PASSWORD || 'my_test_pwd',
    host: process.env.DB_SERVER_HOST || 'localhost',
    port: parseInt( process.env.DB_SERVER_PORT || '3306', 10),
export default MikroOrmConfig;

Then the migration works.

Migration20220714151018.ts successfully created

Solution

  • This was a conflict/typo in my .env file and the source code. The .env file had DB_USER: 'my_test_user' and my code was trying to load DB_USERNAME, so it would obviously not find the entry. Correct the variable usage to match, and the issue is resolved.