@spidy29/env-guardian
v1.0.0
Published
Zero-dependency environment variable validator with automatic type safety and runtime validation
Downloads
18
Maintainers
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 variableenv: Optional environment object (defaults toprocess.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 providedminLength?: number- Minimum string lengthmaxLength?: number- Maximum string lengthpattern?: RegExp- Regex pattern to matchvalidate?: (val: string) => boolean | string- Custom validationtransform?: (val: string) => string- Transform the valuedescription?: 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?: booleandefault?: numbermin?: number- Minimum valuemax?: number- Maximum valueinteger?: boolean- Must be an integervalidate?: (val: number) => boolean | stringtransform?: (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 itemsmaxItems?: 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!
