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

@spidy29/env-guardian

v1.0.0

Published

Zero-dependency environment variable validator with automatic type safety and runtime validation

Downloads

18

Readme

🛡️ env-guardian

Zero-dependency environment variable validator with automatic type safety and runtime validation.

Every backend developer needs this. Stop writing messy environment variable validation code. Get type safety, runtime validation, and crystal-clear error messages - all with zero dependencies.

🎯 Why env-guardian?

Backend developers face this daily:

  • ❌ Messy, repetitive env var parsing code scattered everywhere
  • ❌ Runtime crashes from missing or invalid environment variables
  • ❌ No type safety - everything is a string
  • ❌ Poor error messages when something goes wrong
  • ❌ Heavy validation libraries with tons of dependencies

env-guardian solves all of this:

  • Zero dependencies - Pure TypeScript/JavaScript
  • Full type safety - Automatic TypeScript type inference
  • Runtime validation - Catch errors before your app crashes
  • Clear error messages - Know exactly what's wrong
  • Simple API - Define your schema, get validated config
  • Supports all types - string, number, boolean, enum, URL, email, JSON, arrays
  • Custom validation - Add your own validation logic
  • Transforms - Transform values during validation

📦 Installation

npm install env-guardian

🚀 Quick Start

import { validateEnv, env } from 'env-guardian';

// Define your schema
const config = validateEnv({
  NODE_ENV: env.enum(['development', 'production', 'test'], { 
    default: 'development' 
  }),
  PORT: env.number({ 
    default: 3000,
    min: 1,
    max: 65535 
  }),
  DATABASE_URL: env.url({ 
    protocols: ['postgres', 'postgresql'] 
  }),
  API_KEY: env.string({ 
    minLength: 32 
  }),
  ENABLE_DEBUG: env.boolean({ 
    default: false 
  }),
});

// TypeScript automatically knows the types!
// config.PORT is number
// config.NODE_ENV is 'development' | 'production' | 'test'
// config.ENABLE_DEBUG is boolean

console.log(`Server starting on port ${config.PORT}`);

📖 API Reference

validateEnv(schema, env?)

Validates environment variables against a schema. Throws EnvValidationError if validation fails.

Parameters:

  • schema: Object defining validation rules for each environment variable
  • env: Optional environment object (defaults to process.env)

Returns: Type-safe configuration object

Validators

env.string(options?)

Validates string values.

Options:

  • required?: boolean - Whether the value is required (default: true)
  • default?: string - Default value if not provided
  • minLength?: number - Minimum string length
  • maxLength?: number - Maximum string length
  • pattern?: RegExp - Regex pattern to match
  • validate?: (val: string) => boolean | string - Custom validation
  • transform?: (val: string) => string - Transform the value
  • description?: string - Description for documentation
const config = validateEnv({
  API_KEY: env.string({ 
    minLength: 32,
    maxLength: 128,
    pattern: /^[A-Za-z0-9]+$/
  })
});

env.number(options?)

Validates and converts to number.

Options:

  • required?: boolean
  • default?: number
  • min?: number - Minimum value
  • max?: number - Maximum value
  • integer?: boolean - Must be an integer
  • validate?: (val: number) => boolean | string
  • transform?: (val: string) => number
const config = validateEnv({
  PORT: env.number({ 
    default: 3000,
    min: 1,
    max: 65535,
    integer: true
  })
});

env.boolean(options?)

Validates and converts to boolean. Accepts: true, false, 1, 0, yes, no (case-insensitive).

const config = validateEnv({
  ENABLE_DEBUG: env.boolean({ 
    default: false 
  })
});

env.enum(values, options?)

Validates against a list of allowed values.

const config = validateEnv({
  NODE_ENV: env.enum(['development', 'production', 'test'], { 
    default: 'development' 
  }),
  LOG_LEVEL: env.enum(['debug', 'info', 'warn', 'error'])
});

env.url(options?)

Validates URL format.

Options:

  • protocols?: string[] - Allowed protocols (e.g., ['https', 'http'])
const config = validateEnv({
  DATABASE_URL: env.url({ 
    protocols: ['postgres', 'postgresql'] 
  }),
  API_URL: env.url()
});

env.email(options?)

Validates email format.

const config = validateEnv({
  ADMIN_EMAIL: env.email()
});

env.json(options?)

Parses and validates JSON strings.

const config = validateEnv({
  FEATURE_FLAGS: env.json({ 
    default: { newUI: false, betaFeatures: true }
  })
});

env.array(options?)

Parses comma-separated (or custom separator) strings into arrays.

Options:

  • separator?: string - Separator character (default: ,)
  • minItems?: number - Minimum number of items
  • maxItems?: number - Maximum number of items
const config = validateEnv({
  ALLOWED_ORIGINS: env.array({ 
    separator: ',',
    minItems: 1 
  }),
  TAGS: env.array()
});

🎨 Usage Examples

Basic Web Server

import { validateEnv, env } from 'env-guardian';

const config = validateEnv({
  NODE_ENV: env.enum(['development', 'production'], { 
    default: 'development' 
  }),
  PORT: env.number({ 
    default: 3000 
  }),
  HOST: env.string({ 
    default: '0.0.0.0' 
  }),
});

app.listen(config.PORT, config.HOST, () => {
  console.log(`Server running on ${config.HOST}:${config.PORT}`);
});

Database Configuration

const config = validateEnv({
  DB_HOST: env.string(),
  DB_PORT: env.number({ 
    default: 5432 
  }),
  DB_NAME: env.string(),
  DB_USER: env.string(),
  DB_PASSWORD: env.string({ 
    minLength: 8 
  }),
  DB_SSL: env.boolean({ 
    default: true 
  }),
  DB_POOL_MAX: env.number({ 
    default: 10,
    min: 1,
    max: 100 
  }),
});

API Configuration with Custom Validation

const config = validateEnv({
  API_KEY: env.string({ 
    minLength: 32,
    validate: (val) => {
      if (val.includes(' ')) return 'API key cannot contain spaces';
      if (!/^[A-Za-z0-9]+$/.test(val)) return 'API key must be alphanumeric';
      return true;
    }
  }),
  API_TIMEOUT: env.number({ 
    default: 30000,
    validate: (val) => val >= 1000 || 'Timeout must be at least 1000ms'
  }),
});

Custom Transformations

const config = validateEnv({
  // Convert to uppercase
  REGION: env.string({ 
    transform: (val) => val.toUpperCase()
  }),
  
  // Parse custom format
  CACHE_TTL: env.string({ 
    default: '1h',
    transform: (val) => {
      const match = val.match(/^(\d+)([smhd])$/);
      if (!match) throw new Error('Invalid duration format');
      const [, num, unit] = match;
      const multipliers = { s: 1, m: 60, h: 3600, d: 86400 };
      return parseInt(num) * multipliers[unit as keyof typeof multipliers];
    }
  }),
});

Microservice Configuration

const config = validateEnv({
  // Service info
  SERVICE_NAME: env.string({ default: 'api-service' }),
  SERVICE_VERSION: env.string({ pattern: /^\d+\.\d+\.\d+$/ }),
  
  // Server
  PORT: env.number({ default: 8080 }),
  
  // Database
  DATABASE_URL: env.url({ protocols: ['postgres'] }),
  DB_POOL_MIN: env.number({ default: 2, integer: true }),
  DB_POOL_MAX: env.number({ default: 10, integer: true }),
  
  // Redis
  REDIS_URL: env.url({ protocols: ['redis'], required: false }),
  REDIS_TTL: env.number({ default: 3600 }),
  
  // Security
  JWT_SECRET: env.string({ minLength: 32 }),
  JWT_EXPIRY: env.string({ default: '24h' }),
  ALLOWED_ORIGINS: env.array({ minItems: 1 }),
  
  // Feature flags
  ENABLE_LOGGING: env.boolean({ default: true }),
  LOG_LEVEL: env.enum(['debug', 'info', 'warn', 'error'], { 
    default: 'info' 
  }),
  
  // Advanced
  WORKER_THREADS: env.number({ default: 4, min: 1, max: 16 }),
  NOTIFICATION_CONFIG: env.json({ 
    default: { email: true, sms: false }
  }),
});

🔥 Real-World Example

// config.ts
import { validateEnv, env } from 'env-guardian';

export const config = validateEnv({
  // Environment
  NODE_ENV: env.enum(['development', 'staging', 'production'], {
    default: 'development'
  }),

  // Server
  PORT: env.number({ default: 3000, min: 1, max: 65535 }),
  HOST: env.string({ default: '0.0.0.0' }),

  // Database
  DATABASE_URL: env.url({ protocols: ['postgres', 'postgresql'] }),
  DB_POOL_MIN: env.number({ default: 2, integer: true, min: 1 }),
  DB_POOL_MAX: env.number({ default: 10, integer: true, min: 1 }),

  // Redis Cache
  REDIS_URL: env.url({ protocols: ['redis'], required: false }),
  CACHE_TTL: env.number({ default: 3600, integer: true }),

  // Auth
  JWT_SECRET: env.string({ 
    minLength: 32,
    validate: (val) => !/\s/.test(val) || 'Cannot contain whitespace'
  }),
  JWT_EXPIRY: env.string({ default: '7d', pattern: /^\d+[smhd]$/ }),

  // External APIs
  STRIPE_API_KEY: env.string({ minLength: 20 }),
  SENDGRID_API_KEY: env.string({ minLength: 20 }),
  AWS_REGION: env.string({ default: 'us-east-1' }),
  AWS_S3_BUCKET: env.string(),

  // Security
  ALLOWED_ORIGINS: env.array({ separator: ',', minItems: 1 }),
  RATE_LIMIT_MAX: env.number({ default: 100, integer: true }),

  // Monitoring
  SENTRY_DSN: env.url({ required: false }),
  ENABLE_METRICS: env.boolean({ default: true }),
  LOG_LEVEL: env.enum(['debug', 'info', 'warn', 'error'], {
    default: 'info'
  }),
});

// server.ts
import express from 'express';
import { config } from './config';

const app = express();

app.listen(config.PORT, () => {
  console.log(`🚀 Server running on port ${config.PORT}`);
  console.log(`📊 Environment: ${config.NODE_ENV}`);
  console.log(`💾 Database: ${config.DATABASE_URL}`);
});

🎯 Error Handling

env-guardian provides clear, actionable error messages:

// Missing required variable
Environment validation failed:
  - DATABASE_URL: is required but not provided

// Invalid type
Environment validation failed:
  - PORT: must be a valid number
  - ENABLE_DEBUG: must be a boolean (true/false, 1/0, yes/no)

// Failed validation
Environment validation failed:
  - NODE_ENV: must be one of: development, production, test
  - API_KEY: must be at least 32 characters
  - PORT: must be at least 1000

// Multiple errors
Environment validation failed:
  - DATABASE_URL: must be a valid URL
  - JWT_SECRET: must be at least 32 characters
  - ALLOWED_ORIGINS: must have at least 1 items

🔒 Type Safety

env-guardian provides full TypeScript type inference:

const config = validateEnv({
  PORT: env.number(),
  NODE_ENV: env.enum(['dev', 'prod']),
  ENABLE_CACHE: env.boolean(),
  TAGS: env.array(),
});

// TypeScript knows:
config.PORT           // number
config.NODE_ENV       // 'dev' | 'prod'
config.ENABLE_CACHE   // boolean
config.TAGS           // string[]

🆚 Comparison

| Feature | env-guardian | dotenv | envalid | joi/zod | |---------|-------------|---------|---------|---------| | Zero dependencies | ✅ | ✅ | ❌ | ❌ | | Type inference | ✅ | ❌ | ⚠️ | ✅ | | Runtime validation | ✅ | ❌ | ✅ | ✅ | | Clear error messages | ✅ | ❌ | ✅ | ⚠️ | | Simple API | ✅ | ✅ | ✅ | ❌ | | Custom validators | ✅ | ❌ | ✅ | ✅ | | Bundle size | 3KB | 1KB | 50KB+ | 100KB+ |

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

MIT License - feel free to use this in your projects!

🌟 Why This Package?

Every backend developer deals with environment variables every single day. Most of us have written (or copy-pasted) the same validation code dozens of times. Libraries like Joi and Zod are powerful but overkill for env validation - they're heavy and complex.

env-guardian fills the gap: powerful enough for production, simple enough to start in 30 seconds, and with zero dependencies so it won't bloat your project.

One npm install, one schema definition, and you have type-safe, validated configuration for your entire application.


Made with ❤️ for backend developers who are tired of messy env var handling.

⭐ Star this repo if you find it useful!