Nest JS .env file variables are undefined even though im using ConfigModule - node.js

My variables are undefined but im using .env file in the root of the project that same way it is described in the documentation. Also adding condif imported from 'dotenv' works.
import { config } from 'dotenv';
config();
import { Module } from '#nestjs/common';
import { ConfigModule } from '#nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PodcastsModule } from './podcasts/podcasts.module';
import { TypeOrmModule } from '#nestjs/typeorm';
import { config } from 'dotenv';
config();
const { HOST, PORT, USER, PASSWORD, DATABASE } = process.env;
#Module({
imports: [
ConfigModule.forRoot(),
PodcastsModule,
TypeOrmModule.forRoot({
type: 'postgres',
host: HOST,
port: parseInt(PORT),
username: USER,
password: PASSWORD,
database: DATABASE,
autoLoadEntities: true,
synchronize: true,
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

At the time you are destructuring process.env, dotenv.config() has not yet been ran and the process.env has not beed populated. You can either call dotenv.config() as the very first thing in your main.ts file, or you can use asynchronous registration and use the ConfigService inside of TypeormModule.forRootASync() like so:
#Module({
imports: [
ConfigModule.forRoot(),
PodcastsModule,
TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
type: 'postgres', // you may need to add an `as const` here
host: config.get('HOST'),
port: parseInt(config.get('PORT')),
username: config.get('USER'),
password: config.get('PASSWORD'),
database: config.get('DATABASE'),
autoLoadEntities: true,
synchronize: true,
})
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

Related

can't inject custom repository without #InjectRepository decorator

In NestJS Documentation, it says that when I make custom repository, I don't need to use #InjectRepository() decorator docs
But in my code, I cannot inject my custom repository like that
these are my codes
app.module.ts
#Module({
imports: [
CacheModule.register(),
ConfigModule.forRoot({
isGlobal: true
}),
TypeOrmModule.forRootAsync({
useFactory: () => ({
type: 'postgres',
host: process.env.DB_HOST,
port: +process.env.DB_PORT,
username: process.env.DB_NAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
entities: [`${__dirname}/**/entities/*.entity{.ts,.js}`],
synchronize: true,
logging: true
})
}),
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
cors: {
origin: 'http://localhost:3000',
credentials: true
},
autoSchemaFile: 'schema.gql'
}),
AuthModule,
UserModule,
]
})
export class AppModule {}
user.repository.ts
#EntityRepository(User)
export class UserRepository extends Repository<User> {}
user.module.ts
#Module({
imports: [TypeOrmModule.forFeature([UserRepository]), CacheModule.register()],
providers: [
UserResolver,
UserService,
],
exports: [UserService, TypeOrmModule]
})
export class UserModule {}
user.service.ts
#Injectable()
export class UserService {
constructor(
private readonly userRepository: UserRepository,
#Inject(CACHE_MANAGER) private cacheManager: Cache
) {}
}
error message
ERROR [ExceptionHandler] Nest can't resolve dependencies of the UserService (?, CACHE_MANAGER). Please make sure that the argument UserRepository at index [0] is available in the UserModule context.
Potential solutions:
- If UserRepository is a provider, is it part of the current UserModule?
- If UserRepository is exported from a separate #Module, is that module imported within
UserModule?
#Module({
imports: [ /* the Module containing UserRepository */ ]
})
I don't want to use #InjectRepository(UserRepositry) decorator.
How can I do that?

NestJs: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string

i have a problem with connecting to database in nest.js with typeorm and postgres.
I created a .env file in the root project directory with the following content
POSTGRES_HOST=127.0.0.1
POSTGRES_PORT=5432
POSTGRES_USER=postgres
POSTGRES_PASSWORD=password
POSTGRES_DATABASE=db-name
In the app.module.ts I writed the code below:
import { Module } from '#nestjs/common';
import { ConfigModule } from '#nestjs/config';
import { TypeOrmModule } from '#nestjs/typeorm';
import { FeedModule } from './feed/feed.module';
#Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
TypeOrmModule.forRoot({
type: 'postgres',
host: process.env.POSTGRES_HOST,
port: parseInt(<string>process.env.POSTGRES_PORT),
username: process.env.POSTGRES_USER,
password: process.env.POSTGRES_PASSWORD,
database: process.env.POSTGRES_DATABASE,
autoLoadEntities: true,
synchronize: true,
}),
FeedModule,
],
})
export class AppModule {}
But when im running the app by npm start it throws this error: new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string')
What am I missing or doing wrong?
In NestJs you should use ConfigService to get environment variables inside your typeorm module, read the docs for more information.
You can use it like that:
import { ConfigModule, ConfigService } from '#nestjs/config';
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
#Module({
imports: [
ConfigModule.forRoot(
envFilePath: `.${process.env.NODE_ENV}.env`
),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
injects: [ConfigService],
useFactory: (configService: ConfigService) => ({
type: 'postgres',
host: configService.get("POSTGRES_HOST"),
port: configService.get("POSTGRES_PORT"),
username: configService.get("POSTGRES_USER"),
password: configService.get("POSTGRES_PASSWORD"),
database: configService.get("POSTGRES_DB"),
entities: [],
synchronize: true,
}),
}),
],
controllers: [],
providers: [],
})
export class AppModule {}
As explained in the docs, you can define a factory function where you inject the config-service allowing you to resolve the corresponding values:
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
type: 'postgres',
host: configService.get('POSTGRES_HOST'),
port: +configService.get<number>('POSTGRES_PORT'),
username: configService.get('POSTGRES_USER'),
password: configService.get('POSTGRES_PASSWORD'),
database: configService.get('POSTGRES_DATABASE'),
synchronize: true,
autoLoadEntities: true,
}),
inject: [ConfigService],
});
I was able to fix the problem by using the config module.
Just do npm i #nestjs/config. Then in the imports array just above the TypeOrmModule put ConfigModule.forRoot({ isGlobal: true }),. This allows your module to get the environment variables from the .env file
I got this error because I put the .env file inside the src by mistake. If you put it outside of the src it will fix it
I was facing the same issue and it was weird because I modified several times that configuration just to check if "something new happens" but have no success.
Long story short, I deleted the "dist" folder of the project and build the app again (npm run build) and it worked! It appeared that I had a "bad build" running over and over again so this workaround kind of "refreshed" the build and let things running well again.
Hope this help!

Nest can't resolve dependencies of the JokeEntityRepository (?)

I am learning NestJS and I am trying to test a service which incorporates a repository with TypeORM. It compiles fine without errors, but when I run the test it throw an error.
I know it is a test dependency problem but I can't figure it out. I am trying this test:
describe('JokesService', () => {
let service: JokesService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [],
imports: [
TypeOrmModule.forFeature([JokeEntity])
],
}).compile();
service = module.get<JokesService>(JokesService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
The module:
#Module({
providers: [JokesService],
imports: [
TypeOrmModule.forFeature([JokeEntity])
],
controllers: [JokesController],
})
export class JokesModule {}
The service:
#Injectable()
export class JokesService {
constructor(
#InjectRepository(JokeEntity)
private readonly jokeRepository: MongoRepository<JokeEntity>
) {}
}
The main module:
#Module({
imports: [
TypeOrmModule.forRoot({
type: 'mongodb',
url: dbUri,
entities: [__dirname + '/**/*.entity{.ts,.js}'],
ssl: true,
useUnifiedTopology: true,
useNewUrlParser: true,
}),
JokesModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
And the error:
Nest cant resolve dependencies of the JokeEntityRepository (?).
Please make sure that the argument Connection at index [0] is available in the TypeOrmModule context.
Potential solutions:
- If Connection is a provider, is it part of the current TypeOrmModule?
- If Connection is exported from a separate #Module, is that module imported within TypeOrmModule?
#Module({
imports: [ /* the Module containing Connection */ ]
})
Can someone tell me what I am missing in the test dependencies? Thank You.
Try to import your JokesModule inside your app.module.
#Module({
imports: [
TypeOrmModule.forRoot({
type: 'mongodb',
url: dbUri,
entities: [__dirname + '/**/*.entity{.ts,.js}'],
ssl: true,
useUnifiedTopology: true,
useNewUrlParser: true,
}),
JokesModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

NestJS ConfigService returns undefined values during async TypeORM configuration on app startup

I'm trying to setup configuration for my NestJS app by following some of the following documentation:
Config: https://docs.nestjs.com/techniques/configuration
TypeORM: https://docs.nestjs.com/techniques/database#async-configuration
I've added a .env file to the root of my project (same level as package.json) with the following values:
DB_URL=localhost
DB_USER=root
DB_PASSWORD=root
DB_NAME=test_db
In my app.module.ts, I import the following modules:
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
import { ConfigModule, ConfigService } from '#nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
#Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => {
// The value logged below is undefined'
console.log(`DB URL: ${configService.get('DB_URL')}`);
return {
type: 'mysql',
host: configService.get('DB_URL'),
port: 3306,
username: configService.get('DB_USER'),
password: configService.get('DB_PASSWORD'),
database: configService.get('DB_NAME'),
entities: ['dist/**/*.entity{.ts,.js}'],
synchronize: false,
migrations: ['dist/migrations/*{.js}'],
cli: {
migrationsDir: 'migrations',
},
};
},
inject: [ConfigService],
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
As noted above, the value retrieved by configService.get('DB_URL') is undefined. Was hoping for any help/advice on how to set up the configuration so that I could read the values in my .env file when starting up the application.

Type string is not assignable to type '"mysql"'

I have two files environemtn.ts where I stored database configs info, I called vars in app.module.ts file but it cannot getting value Type string is not assignable to type '"mysql"'
Following code of environment.ts
const path = require('path');
export const environment = {
/* Configurations used for TypeORM */
database_type: 'mysql',
database_username: 'root',
database_name: 'database_name',
database_password: null,
database_port: '3306',
database_prefix: 'prefix_',
database_host: 'localhost',
encrypt:true,
synchronize: false,
migrationsRun: false,
logging: true,
};
Following code of app.module.ts file
import { Module } from '#nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '#nestjs/typeorm';
import { environment } from '../environments/environment';
#Module({
imports: [TypeOrmModule.forRoot({
type: environment.database_type,
host: environment.database_host,
port: environment.database_port,
username: environment.database_username,
password: environment.database_password,
database: environment.database_name,
entities: [],
synchronize: true,
})],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
type option expected a string literal type not a string: read more about string literal type
import {ConnectionOptions, DatabaseType} from 'typeorm';
.....
const dataBaseType: DatabaseType = environment.database_type;
#Module({
imports: [TypeOrmModule.forRoot({
type: dataBaseType,
host: environment.database_host,
port: environment.database_port,
username: environment.database_username,
password: environment.database_password,
database: environment.database_name,
entities: [],
synchronize: true,
})],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

Resources