0

I set up a NestJS project that uses TypeORM with Postgres - Docker. TypeORM successfully connects to my Postgres DB when I hardcode the connection values into the config, but not when using environment variables.

To test whether .env vars get read at all, I tried console.log-ing them from main.ts and the values were read without issue, but for some reason replacing the hard coded values with ENV vars results in the error: SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string for the DB connection

Below is my TypeORM config where the values should be read

import { registerAs } from '@nestjs/config';
import { join } from 'path';
import { DataSourceOptions } from 'typeorm';

export const typeormConfig = registerAs(
  'typeorm',
  (): 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,
    synchronize: false,
    logging: false,
    entities: [],
    migrations: [join(__dirname, './migrations/**/*.{ts,js}'), join(__dirname, './seeds/**/*.{ts,js}')],
  }),
);

Here is my app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { TypeOrmModule, TypeOrmModuleAsyncOptions, TypeOrmModuleOptions } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { configsArray } from './config';
import { LoggerModule } from 'nestjs-pino';

@Module({
  imports: [
    ConfigModule.forRoot({ load: configsArray }),
    TypeOrmModule.forRootAsync({
      inject: [ConfigService],
      imports: [ConfigModule],
      useFactory: (configService: ConfigService): TypeOrmModuleAsyncOptions =>
        configService.get<TypeOrmModuleOptions>('typeorm'),
    }),
    LoggerModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (config: ConfigService) => config.get('pino'),
    }),
  ],
  controllers: [AppController],
  providers: [],
})
export class AppModule {}

And main.ts where the password is successfully logged

import { INestApplication, ValidationPipe, ValidationPipeOptions, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { NestFactory } from '@nestjs/core';
import { LoggerErrorInterceptor, Logger as Pino } from 'nestjs-pino';
import { AppDataSource } from 'ormconfig';
import { AppModule } from './app.module';
import { TypeOrmExceptionFilter } from './shared/exceptions/type-orm-exception.filter';
import { TimeoutInterceptor } from './shared/interceptors/timeout.interceptor';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, { cors: true });
  console.log(process.env.POSTGRES_PASSWORD);
  const configService: ConfigService = app.get(ConfigService);
  const PORT: string = configService.get('server.port');
  const HOST: string = configService.get('server.host');
  const VALIDATION_PIPE: ValidationPipeOptions = configService.get('validation-pipe');

  app.useGlobalPipes(new ValidationPipe(VALIDATION_PIPE));
  app.useGlobalFilters(new TypeOrmExceptionFilter());
  app.useGlobalInterceptors(new LoggerErrorInterceptor());
  app.useGlobalInterceptors(new TimeoutInterceptor());
  app.useLogger(app.get(Pino));
  const logger: Logger = new Logger('main.ts');

  AppDataSource.initialize()
  .then(() => {
    console.log('Connected to Data Source');
  })
  .catch((err) => {
    console.error('Error during Data Source initialization', err);
  });

  await app.listen(PORT, HOST);
  logger.log(`Server has been started on HOST: ${HOST}, PORT: ${PORT}`);
}
bootstrap();

So I can confirm that I am not using the wrong DB connection values and .env vars do get read from other files.

I would appreciate any help on what might be the issue here.

1
  • are you sure that your environment (docker container) has that .env file or the env. vars injected into the shell? Commented Feb 23, 2023 at 16:21

1 Answer 1

0

you should add

// eslint-disable-next-line @typescript-eslint/no-var-requires

require('dotenv').config(); into your typeormConfig file

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, this solved it! I tried this in main.ts as some answers on similar questions suggested and it didn't work, but I only just realized it was because they had their typeorm config in main.ts not in a separate file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.