npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

envolution

v1.4.1

Published

TypeScript-first environment configuration with Zod validation, .env support, hot reloading, and startup validation. Zero-config setup - just install and use! Perfect for Node.js, AWS Lambda, and modern TypeScript applications.

Readme

envolution

npm version License: MIT TypeScript Node.js

A TypeScript-first environment configuration package with Zod validation, type safety, extensible schemas, .env file support, hot reloading, and startup validation. Perfect for Node.js, AWS Lambda, and modern TypeScript applications.

📋 Table of Contents

Features

  • 🔒 Type Safety: Full TypeScript support with inferred types
  • Validation: Runtime validation with helpful error messages using Zod
  • 📝 .env File Support: Loads environment variables from .env files automatically
  • 🔄 Hot Reloading: Watch for file changes and reload configuration automatically
  • 🚦 Startup Validation: Validate all required config at startup
  • 🔧 Extensibility: Easy to extend with custom schemas
  • 📋 Template Generation: Generate .env templates and TypeScript types from schemas
  • 🚀 Singleton Pattern: Thread-safe singleton instance
  • ☁️ AWS Optimized: Built-in AWS-specific schemas
  • 📦 Zero Dependencies: Includes all dependencies - no setup required
  • 🌳 Tree Shakeable: Modular exports for optimal bundle size
  • 🔄 Dual Module Support: Works with both CommonJS and ES Modules
  • 🧪 Well Tested: Comprehensive test coverage

Installation

npm install envolution

✨ Zero-config setup! envolution includes all its dependencies (zod and dotenv) - no need to install anything else.

Module Compatibility

envolution supports both CommonJS and ES Modules:

CommonJS

const { EnvironmentConfig, BaseEnvironmentSchema } = require('envolution');

ES Modules

import { EnvironmentConfig, BaseEnvironmentSchema } from 'envolution';

The package automatically detects your project's module system and provides the appropriate format.

Why envolution?

| Feature | envolution | dotenv | config | convict | |---------|------------|--------|--------|---------| | TypeScript Support | ✅ Full type safety | ❌ No types | ❌ Basic types | ❌ No types | | Runtime Validation | ✅ Zod schemas | ❌ No validation | ❌ No validation | ✅ Basic validation | | Hot Reloading | ✅ Built-in | ❌ No | ❌ No | ❌ No | | Template Generation | ✅ Auto-generate .env templates | ❌ Manual | ❌ Manual | ❌ Manual | | AWS Optimized | ✅ Built-in schemas | ❌ No | ❌ No | ❌ No | | Startup Validation | ✅ Built-in | ❌ No | ❌ No | ❌ No | | Bundle Size | ✅ Tree-shakeable | ✅ Small | ❌ Large | ❌ Large | | Zero Dependencies | ✅ Standalone package | ✅ Yes | ❌ Many deps | ❌ Many deps |

Quick Start

Basic Usage

import { EnvironmentConfig, BaseEnvironmentSchema } from 'envolution';

// Get environment config with base schema (loads .env by default)
const env = EnvironmentConfig.getInstance(BaseEnvironmentSchema);

// Get values
const stage = env.get('STAGE'); // 'dev' | 'prod' | 'test'
const logLevel = env.get('LOG_LEVEL'); // 'debug' | 'info' | 'warn' | 'error'

// Get required values (throws if missing)
const serviceName = env.getRequired('SERVICE_NAME', 'MyService');

// Convenience getters
console.log(`Running in ${env.stage} mode`);
console.log(`Is production: ${env.isProduction}`);
console.log(`Is development: ${env.isDevelopment}`);

.env File Support

By default, .env and .env.local files are loaded automatically. You can customize which files to load:

const env = EnvironmentConfig.getInstance(BaseEnvironmentSchema, {
  envFiles: ['.env', '.env.production'], // custom list
  loadEnvFiles: true // (default)
});

Hot Reloading

Enable hot-reloading to automatically reload configuration when files change:

const env = EnvironmentConfig.getInstance(MySchema, {
  hotReload: true,
  watchFiles: true,
  watchInterval: 5000, // Check every 5 seconds
});

// Listen for configuration changes
env.on('configChanged', (change) => {
  console.log(`Variable ${change.variable} changed from ${change.oldValue} to ${change.newValue}`);
});

// Listen for specific variable changes
env.on('configChanged:PORT', (change) => {
  console.log(`Port changed to ${change.newValue}`);
});

// Manual reload
env.reload();

// Stop watching (cleanup)
env.stopWatching();

Template Generation

Generate .env templates and TypeScript types from your schemas:

import { generateEnvTemplate, generateTypes, generateAllTemplates } from 'envolution';

// Generate .env template
const envTemplate = generateEnvTemplate(MySchema, {
  includeDefaults: true,
  includeComments: true,
  outputFile: '.env.template'
});

// Generate TypeScript types
const typesTemplate = generateTypes(MySchema, {
  outputFile: 'env.types.ts'
});

// Generate all templates at once
const allTemplates = generateAllTemplates(MySchema, {
  envFile: '.env.template',
  typesFile: 'env.types.ts'
});

Startup Validation

You can validate all required config at startup (throws if any required variable is missing or invalid):

const env = EnvironmentConfig.getInstance(BaseEnvironmentSchema, {
  validateStartup: true
});
// If any required variable is missing/invalid, an error is thrown immediately

Or call manually:

env.validateStartup();

Custom Schema

import { z } from 'zod';
import { createEnvironmentConfig, BaseEnvironmentSchema, mergeSchemas } from 'envolution';

// Define custom schema
const DatabaseSchema = z.object({
  DATABASE_URL: z.string().url(),
  DATABASE_POOL_SIZE: z.string().transform(Number).pipe(z.number().positive()).default('10'),
  DATABASE_TIMEOUT: z.string().transform(Number).pipe(z.number().positive()).default('5000'),
});

// Merge with base schema
const FullSchema = mergeSchemas(BaseEnvironmentSchema, DatabaseSchema);

// Create environment config with custom schema (no type casting needed!)
const env = createEnvironmentConfig(FullSchema);

// Now you have type safety for database variables
const dbUrl = env.getRequired('DATABASE_URL', 'Database connection');
const poolSize = env.get('DATABASE_POOL_SIZE'); // number
const timeout = env.get('DATABASE_TIMEOUT'); // number

AWS Lambda Usage

import { EnvironmentConfig, mergeSchemas, BaseEnvironmentSchema, AWSEnvironmentSchema } from 'envolution';

// Create schema for AWS Lambda
const LambdaSchema = mergeSchemas(BaseEnvironmentSchema, AWSEnvironmentSchema);

// Get environment config
const env = EnvironmentConfig.getInstance(LambdaSchema);

// Lambda handler
export const handler = async (event: Record<string, unknown>) => {
  // Get AWS-specific environment variables
  const stage = env.stage;
  const region = env.get('AWS_REGION');
  const stateMachineArn = env.getRequired('STATE_MACHINE_ARN', 'Step Function');
  const jobTableName = env.getRequired('JOB_TABLE_NAME', 'Job table');
  
  // Your Lambda logic here...
  return {
    statusCode: 200,
    body: JSON.stringify({ message: 'Success' }),
  };
};

Available Schemas

Base Schema

Includes common configuration options:

  • STAGE: Environment stage ('dev', 'prod', 'test')
  • NODE_ENV: Node environment
  • LOG_LEVEL: Logging level
  • SERVICE_NAME: Service name
  • VERSION: Application version
  • ENABLE_DEBUG: Debug mode flag
  • ENABLE_METRICS: Metrics collection flag
  • REQUEST_TIMEOUT: Request timeout
  • MAX_RETRIES: Maximum retry attempts

AWS Schema

Includes AWS-specific variables:

  • AWS_REGION: AWS region
  • AWS_ACCOUNT_ID: AWS account ID
  • STATE_MACHINE_ARN: Step Function ARN
  • QUOTA_TABLE: DynamoDB quota table
  • JOB_TABLE_NAME: DynamoDB job table
  • QUEUE_URL: SQS queue URL
  • MODEL_ID: Bedrock model ID
  • LAMBDA_TIMEOUT: Lambda timeout
  • LAMBDA_MEMORY_SIZE: Lambda memory size

Security Schema

Includes security-related variables:

  • JWT_SECRET: JWT signing secret
  • JWT_EXPIRES_IN: JWT expiration time
  • API_KEY: API key
  • ENCRYPTION_KEY: Encryption key
  • CORS_ORIGIN: CORS origin
  • RATE_LIMIT_WINDOW: Rate limiting window
  • RATE_LIMIT_MAX_REQUESTS: Rate limiting max requests

API Reference

EnvironmentConfig

getInstance<T>(schema?, options?)

Get singleton instance of EnvironmentConfig. Note: You must call this method explicitly to configure options like suppressWarnings. There is no automatic env export to prevent unwanted initialization.

Options:

  • envFiles: string[] — Which .env files to load (default: ['.env', '.env.local'])
  • loadEnvFiles: boolean — Whether to load .env files (default: true)
  • validateStartup: boolean — Whether to validate all config at startup (default: false)
  • hotReload: boolean — Whether to enable hot-reloading (default: false)
  • watchFiles: boolean — Whether to watch for file changes (default: false)
  • watchInterval: number — Interval in milliseconds to check for changes (default: 5000)
  • suppressWarnings: boolean — Whether to suppress warning logs for missing/invalid env files (default: false)
const env = EnvironmentConfig.getInstance(MySchema, { validateStartup: true });

CLI Applications: Use suppressWarnings: true to prevent warning logs from appearing to end users:

const env = EnvironmentConfig.getInstance(MySchema, { 
  suppressWarnings: true, // Hide warnings from end users
  validateStartup: true 
});

get<K>(key)

Get a configuration value.

const value = env.get('MY_VARIABLE');

getRequired<K>(key, context?)

Get a required configuration value (throws if undefined/null).

const value = env.getRequired('MY_VARIABLE', 'MyService');

getAll()

Get all configuration values.

const allConfig = env.getAll();

validateStartup()

Validate all required config at startup (throws if any required variable is missing or invalid).

env.validateStartup();

reload()

Manually trigger configuration reload.

env.reload();

stopWatching()

Stop watching for file changes and cleanup resources.

env.stopWatching();

Event Listeners

Listen for configuration changes:

// General configuration change
env.on('configChanged', (change) => {
  console.log(`${change.variable} changed to ${change.newValue}`);
});

// Specific variable change
env.on('configChanged:PORT', (change) => {
  console.log(`Port changed to ${change.newValue}`);
});

// Configuration reloaded
env.on('configReloaded', (event) => {
  console.log('Configuration reloaded successfully');
});

// Reload error
env.on('configReloadError', (error) => {
  console.error('Failed to reload configuration:', error);
});

stage, isProduction, isDevelopment, isTest

Convenience getters for environment stage.

const stage = env.stage; // 'dev' | 'prod' | 'test'
const isProd = env.isProduction; // boolean
const isDev = env.isDevelopment; // boolean
const isTest = env.isTest; // boolean

Schema Utilities

mergeSchemas(schema1, schema2)

Merge two schemas together.

const FullSchema = mergeSchemas(BaseSchema, CustomSchema);

mergeMultipleSchemas(...schemas)

Merge multiple schemas together.

const FullSchema = mergeMultipleSchemas(Schema1, Schema2, Schema3);

createCustomSchema(schema)

Create a custom schema with proper typing.

const CustomSchema = createCustomSchema(z.object({...}));

createLooseSchema(schema)

Create a schema that allows unknown properties.

const LooseSchema = createLooseSchema(MySchema);

createStrictSchema(schema)

Create a schema with strict validation.

const StrictSchema = createStrictSchema(MySchema);

Template Generation

generateEnvTemplate(schema, options?)

Generate .env template from schema.

const template = generateEnvTemplate(MySchema, {
  includeDefaults: true,
  includeComments: true,
  outputFile: '.env.template'
});

generateTypes(schema, options?)

Generate TypeScript types from schema.

const types = generateTypes(MySchema, {
  outputFile: 'env.types.ts'
});

generateAllTemplates(schema, options?)

Generate all templates at once.

const allTemplates = generateAllTemplates(MySchema, {
  envFile: '.env.template',
  typesFile: 'env.types.ts'
});

Environment Variables

Set these environment variables in your application (or in a .env file):

# Base configuration
STAGE=dev
LOG_LEVEL=info
SERVICE_NAME=my-service
ENABLE_DEBUG=false
ENABLE_METRICS=true

# AWS configuration
AWS_REGION=us-east-1
STATE_MACHINE_ARN=arn:aws:states:...
JOB_TABLE_NAME=my-jobs-table
QUEUE_URL=https://sqs.us-east-1.amazonaws.com/...

# Security configuration
JWT_SECRET=your-super-secret-jwt-key-here
API_KEY=your-api-key

Error Handling

When validation fails, you get detailed error messages:

try {
  const env = EnvironmentConfig.getInstance(MySchema, { validateStartup: true });
} catch (error) {
  if (error instanceof EnvironmentConfig.EnvironmentValidationError) {
    console.error(error.message);
    // Example:
    // Environment validation failed at startup.
    // Missing required variables: DATABASE_URL, API_KEY
    // Invalid variables: PORT (expected valid value, got 'abc')
    console.error('Missing:', error.missingVars);
    console.error('Invalid:', error.invalidVars);
  } else {
    throw error;
  }
}

Testing

For testing, you can reset the singleton instance:

import { EnvironmentConfig } from 'envolution';

beforeEach(() => {
  EnvironmentConfig.reset();
});

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

License

MIT License - see LICENSE file for details.