Overview
Validate environment variables at startup with Zod. Provides typed access to configuration.
Features
- Zod schema validation
- Startup validation
- Type-safe getters
- Environment helpers
Installation
npx hanma add config-provider --framework nest
Dependencies
zod
Code
import { Injectable, OnModuleInit, Logger } from "@nestjs/common";
import { z } from "zod";
// Define your configuration schema
const ConfigSchema = z.object({
// Application
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
PORT: z.coerce.number().default(3000),
API_PREFIX: z.string().default("api"),
// Database
DATABASE_URL: z.string().url(),
DB_POOL_SIZE: z.coerce.number().min(1).max(100).default(10),
// Redis
REDIS_HOST: z.string().default("localhost"),
REDIS_PORT: z.coerce.number().default(6379),
REDIS_PASSWORD: z.string().optional(),
// JWT
JWT_SECRET: z.string().min(32),
JWT_EXPIRES_IN: z.string().default("7d"),
JWT_REFRESH_EXPIRES_IN: z.string().default("30d"),
// CORS
CORS_ORIGIN: z.string().default("*"),
// Optional external services
AWS_ACCESS_KEY_ID: z.string().optional(),
AWS_SECRET_ACCESS_KEY: z.string().optional(),
AWS_REGION: z.string().default("us-east-1"),
S3_BUCKET: z.string().optional(),
// Logging
LOG_LEVEL: z.enum(["error", "warn", "info", "debug", "verbose"]).default("info"),
});
export type Config = z.infer<typeof ConfigSchema>;
@Injectable()
export class ConfigService implements OnModuleInit {
private readonly logger = new Logger(ConfigService.name);
private config: Config;
onModuleInit() {
this.validateConfig();
}
private validateConfig() {
const result = ConfigSchema.safeParse(process.env);
if (!result.success) {
const errors = result.error.issues.map(
(issue) => ` - ${issue.path.join(".")}: ${issue.message}`
);
this.logger.error(
`Configuration validation failed:\n${errors.join("\n")}`
);
throw new Error("Invalid configuration. Check environment variables.");
}
this.config = result.data;
this.logger.log("Configuration validated successfully");
}
get<K extends keyof Config>(key: K): Config[K] {
return this.config[key];
}
getOrThrow<K extends keyof Config>(key: K): NonNullable<Config[K]> {
const value = this.config[key];
if (value === undefined || value === null) {
throw new Error(`Configuration key "${key}" is not set`);
}
return value as NonNullable<Config[K]>;
}
getAll(): Readonly<Config> {
return Object.freeze({ ...this.config });
}
// Type-safe getters for common configurations
get isDevelopment(): boolean {
return this.config.NODE_ENV === "development";
}
get isProduction(): boolean {
return this.config.NODE_ENV === "production";
}
get isTest(): boolean {
return this.config.NODE_ENV === "test";
}
get port(): number {
return this.config.PORT;
}
get databaseUrl(): string {
return this.config.DATABASE_URL;
}
get jwtConfig() {
return {
secret: this.config.JWT_SECRET,
expiresIn: this.config.JWT_EXPIRES_IN,
refreshExpiresIn: this.config.JWT_REFRESH_EXPIRES_IN,
};
}
get redisConfig() {
return {
host: this.config.REDIS_HOST,
port: this.config.REDIS_PORT,
password: this.config.REDIS_PASSWORD,
};
}
get awsConfig() {
return {
accessKeyId: this.config.AWS_ACCESS_KEY_ID,
secretAccessKey: this.config.AWS_SECRET_ACCESS_KEY,
region: this.config.AWS_REGION,
s3Bucket: this.config.S3_BUCKET,
};
}
get corsOrigins(): string[] {
return this.config.CORS_ORIGIN.split(",").map((o) => o.trim());
}
}
// Usage:
/*
import { ConfigService } from "./providers/config.service";
@Injectable()
export class SomeService {
constructor(private readonly config: ConfigService) {}
doSomething() {
const port = this.config.get("PORT");
const dbUrl = this.config.databaseUrl;
if (this.config.isDevelopment) {
// Development-only code
}
}
}
*/
Usage
const port = this.config.get('PORT');
const jwt = this.config.jwtConfig;
Dependencies
zod
Frequently Asked Questions
How do I install Config Service?
Run the following command:
npx hanma add config-provider --framework nestWhat dependencies are required?
This snippet requires: zod. Make sure to install them before using the snippet.
How do I use this snippet?
Copy the code and paste it into your project. The snippet will be saved to
src/providers/config.service.ts.Can I customize this snippet?
Yes! All snippets are copy-paste code that you own. Feel free to modify them to fit your needs.
Does this work with other frameworks?
This snippet is designed for the specific framework. Check the other framework pages for equivalent implementations.