Skip to content

Instantly share code, notes, and snippets.

@emildimitrov
Last active January 22, 2023 19:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emildimitrov/27bb02266f166944ced64d0524a3d4bb to your computer and use it in GitHub Desktop.
Save emildimitrov/27bb02266f166944ced64d0524a3d4bb to your computer and use it in GitHub Desktop.
Best nestjs config approach
  • Can be used without DI - just instantiate
  • You get types - no explicit type imports etc
  • You can define computed fields etc
  • You can refactor ENV names without affecting the service fields :)
  • You can structure and nest the fileds however you want
  • Super simple to reason about & maintain - no need to rely on magic
import { Global, Module } from '@nestjs/common';
import { ConfigService } from './config.service';
@Global()
@Module({
providers: [ConfigService],
exports: [ConfigService],
})
export class ConfigModule {}
import {
IsBoolean,
IsEnum,
IsNotEmpty,
IsNumber,
IsOptional,
} from 'class-validator';
export class ConfigOptions {
//mind boolean casting with class-transformer - use decorator @ToBoolean
@IsBoolean()
@IsOptional()
DEBUG?: boolean = false;
@IsNotEmpty()
POSTGRES_HOST: string;
@IsNotEmpty()
POSTGRES_USERNAME: string;
@IsNotEmpty()
POSTGRES_PASSWORD: string;
@IsNotEmpty()
REDIS_HOST: string;
}
import { Injectable } from '@nestjs/common';
import { plainToClass } from 'class-transformer';
import { validateSync } from 'class-validator';
import * as dotenv from 'dotenv';
import { ConfigOptions } from './config.options';
//sets to process.env what we have in .env
dotenv.config();
/**
* @description
* - Can be used without DI - just instantiate
* - You get types - no explicit type imports etc
* - You should expose getter for each field you want
* - You can define computed fields etc, but everything
* - You can refactor ENV names without affecting the service fields :)
* which this service exposes should be read only
* - prefer grouping fields with same prefix - makes things more readable
* @export
* @class ConfigService
*/
@Injectable()
export class ConfigService {
private readonly env: ConfigOptions;
constructor() {
const transformed = plainToClass(ConfigOptions, process.env);
const errors = validateSync(transformed, {
/**
* Will strip not declared with decorator in options fields
*/
whitelist: true,
});
if (errors.length > 0) {
errors.forEach((e) => {
console.error(e.toString());
});
process.exit(1);
}
this.env = transformed;
}
get debug() {
return this.env.DEBUG;
}
get postgres() {
return {
host: this.env.POSTGRES_HOST,
username: this.env.POSTGRES_USERNAME,
password: this.env.POSTGRES_PASSWORD,
};
}
get redis() {
return {
host: this.env.REDIS_HOST,
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment