Env-Core: An Easy Way to Validate Environment Variables in Node.js Projects

Emmanuel Nwankwo - Oct 26 - - Dev Community

Managing environment variables effectively is crucial in Node.js applications, but existing solutions can feel limiting or lack the flexibility needed for complex setups. Frustrated by these challenges, I developed env-core. Let me tell you about it.

Introduction to env-core

env-core is a powerful yet simple npm package for validating environment variables in Node.js applications. Built with TypeScript and compatible with Express and NestJS frameworks, env-core ensures that your configurations are always type-safe, complete, and ready for production. By leveraging dotenv as its sole dependency, env-core works to validate your environment variables before your application even starts.

Key Features

  • Type Safety: Leveraging TypeScript, env-core offers strong typing for environment variables, reducing runtime errors and improving overall code quality.
  • Seamless Integration: Compatible with both Express and NestJS, env-core is a good fit for new projects or as a replacement in existing applications.
  • Flexible Configuration: Supports various data types (e.g., strings, numbers, and booleans), allowing complex configurations to fit seamlessly into your project.
  • Default Values: Set default values for optional variables, so your app always has a fallback if a variable is missing.
  • Validation: With built-in validation, you can catch configuration errors early and avoid misconfigurations in production.
  • CommonJS and ESM Support: Works effortlessly with ESM (import) and CommonJS (require) modules, giving you flexibility based on your project setup.

Getting Started

To start using env-core in your project, simply install it via npm:

npm install env-core
Enter fullscreen mode Exit fullscreen mode

After installation, you can integrate env-core into your application with ease. Here's an example to get you started:

import { validateEnv } from 'env-core';

const env = validateEnv({
  PORT: Number,
  DATABASE_URL: String,
  DEBUG: Boolean,
});

console.log(env.PORT); // Typed as number
console.log(env.DATABASE_URL); // Typed as string
console.log(env.DEBUG); // Typed as boolean
Enter fullscreen mode Exit fullscreen mode

env-core supports both ESM and CommonJS modules, so if you’re using CommonJS, you can import it like this:

const { validateEnv } = require('env-core');
Enter fullscreen mode Exit fullscreen mode

Use Cases

env-core offers flexible configuration options based on your project’s needs. Here are three use cases that show how you can set up an environment schema with various levels of configuration:

Use Case 1: Simple Types

In this basic setup, each environment variable is typed with a primitive type.

// src/envSchema.js
export const envSchema = {
  PORT: Number,
  DATABASE_URL: String,
  DEBUG: Boolean,
  NODE_ENV: String,
};
Enter fullscreen mode Exit fullscreen mode

Use Case 2: Configuration Options

You can include default values and exclude requirement checks for specific environment variables.

Use Case 2: Configuration Options

This setup allows you to include default values and specify which variables are optional.

// src/envSchema.ts
export const envSchema = {
  PORT: { type: Number, default: 3000, required: false },
  DATABASE_URL: { type: String },
  DEBUG: { type: Boolean, default: false },
  NODE_ENV: { type: String, default: 'development', required: false },
};
Enter fullscreen mode Exit fullscreen mode

Use Case 3: Mixed Configuration

For flexibility, you can use a mix of simple types and configuration options.

// src/envSchema.ts
export const envSchema = {
  PORT: Number,
  DATABASE_URL: String,
  DEBUG: { type: Boolean, default: false },
  NODE_ENV: { type: String, default: 'production', required: false },
};
Enter fullscreen mode Exit fullscreen mode

Framework-Specific Use Cases

env-core easily integrates with Express and NestJS, making environment variable validation a simple step during the initialization process.

ExpressJS Example

In Express, validate your environment variables before starting the server:

// src/index.js
import express from 'express';
import { validateEnv } from 'env-core';
import { envSchema } from './envSchema';

const env = validateEnv(envSchema); // Option 1: Validates using environment variables or defaults to .env
// const env = validateEnv(envSchema, 'test.env'); // Option 2: Validates using a custom env file

const app = express();
app.listen(env.PORT, () => {
    console.log(`Server is running on port ${env.PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

NestJS Example

In NestJS, integrate env-core validation within the module initialization:

// src/app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { validateEnv } from 'env-core';
import { envSchema } from './envSchema';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      validate: (config) => validateEnv(envSchema, config), // Validate environment variables
    }),
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

Why Choose env-core?

Compared to other packages, env-core offers:

  • Type Safety: Strong typing reduces runtime errors and improves overall reliability.
  • Graceful Startup Failure: If a critical variable is missing or invalid, env-core will prevent your application from starting, allowing you to address configuration issues upfront.
  • Flexible Fallbacks: Optional fields with default values ensure that your application can adapt to different environments (e.g., staging vs. production).
  • Enhanced Clarity: By defining environment variables in a schema or interface, you gain visibility into your application’s configuration requirements.

Found env-core useful? check out the code on GitHub and consider giving it a star to show your support! Your feedback is valuable, so please don’t hesitate to open an issue if you encounter any problems or have ideas for improvements.

.
Terabox Video Player