Careeroza
ConfigModule and .env Files
Never Hard-code Secrets
Database URLs, JWT secrets and API keys change between your laptop, staging and production. Keep them in environment variables, loaded from a .env file in development.
Example
npm i @nestjs/configExample output
added 4 packages in 3s
The .env file
.env
PORT=3000
NODE_ENV=development
DATABASE_URL=postgresql://shopease:secret@localhost:5432/shopease
JWT_SECRET=change-me-in-production
RAZORPAY_KEY_ID=rzp_test_1DP5mmOlF5G5agNote: Add .env to .gitignore. Commit a .env.example with dummy values instead.
ConfigModule and ConfigService
src/app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true, // no need to import it in every module
envFilePath: ['.env.local', '.env'], // first file wins
cache: true,
}),
],
})
export class AppModule {}src/payments/razorpay.service.ts
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class RazorpayService {
private readonly keyId: string;
constructor(private readonly config: ConfigService) {
this.keyId = this.config.getOrThrow<string>('RAZORPAY_KEY_ID'); // throws if missing
}
port() {
return this.config.get<number>('PORT', 3000); // default value
}
}Typed Config Namespaces
src/config/database.config.ts
import { registerAs } from '@nestjs/config';
export default registerAs('database', () => ({
url: process.env.DATABASE_URL,
poolSize: parseInt(process.env.DB_POOL_SIZE ?? '10', 10),
ssl: process.env.NODE_ENV === 'production',
}));
// app.module.ts: ConfigModule.forRoot({ isGlobal: true, load: [databaseConfig] })
// usage: this.config.get<number>('database.poolSize')