@opensourcesforge/envguard
v1.1.1
Published
Type-safe environment variable validation with superior TypeScript inference, zero dependencies, and advanced features like secret masking, nested objects, and .env.example generation
Downloads
301
Maintainers
Readme
EnvGuard
Type-safe environment variable validation for Node.js, Bun, and other JavaScript runtimes.
Features
- Type-safe: Full TypeScript support with automatic type inference
- Zero dependencies: Lightweight with no external dependencies
- Comprehensive validators: Built-in validators for strings, numbers, booleans, emails, URLs, UUIDs, durations, byte sizes, and more
- Custom validators: Easy to create your own validators
- Secret masking: Automatically mask sensitive values in error messages
- Flexible defaults: Support for
default,devDefault, andtestDefaultvalues - Conditional requirements: Make variables required based on other values
- Warning mode: Non-blocking validation for optional variables
- Extra variable detection: Warn or error on unknown environment variables
- Immutable output: Validated environment is frozen and protected
- .env.example generation: Auto-generate example files from your schema
- Colored error output: Beautiful, readable error messages
Installation
npm install envguardQuick Start
import { cleanEnv, str, num, bool, email, url } from 'envguard';
const env = cleanEnv({
PORT: num({ default: 3000 }),
HOST: str({ default: 'localhost' }),
DATABASE_URL: url(),
API_KEY: str({ secret: true }),
DEBUG: bool({ default: false }),
ADMIN_EMAIL: email({ default: '[email protected]' }),
});
// Fully typed!
console.log(env.PORT); // number
console.log(env.HOST); // string
console.log(env.DATABASE_URL); // string
console.log(env.DEBUG); // boolean
// Environment helpers
console.log(env.isProduction); // boolean
console.log(env.isDevelopment); // boolean
console.log(env.isTest); // booleanValidators
Basic Validators
str(options?)
Validates string values.
import { str } from 'envguard';
const env = cleanEnv({
// Basic string
NAME: str(),
// With default
HOST: str({ default: 'localhost' }),
// With validation
CODE: str({
minLength: 3,
maxLength: 10,
pattern: /^[A-Z]+$/,
}),
// With transformation
SLUG: str({
trim: true,
toLowerCase: true,
}),
// With choices
NODE_ENV: str({
choices: ['development', 'staging', 'production'],
}),
});num(options?)
Validates numeric values.
import { num } from 'envguard';
const env = cleanEnv({
PORT: num({ default: 3000 }),
// With constraints
MAX_CONNECTIONS: num({
min: 1,
max: 100,
integer: true,
}),
// With choices
RETRY_COUNT: num({
choices: [1, 3, 5, 10],
}),
});bool(options?)
Validates boolean values. Accepts: 1, 0, true, false, yes, no, on, off, t, f, y, n.
import { bool } from 'envguard';
const env = cleanEnv({
DEBUG: bool({ default: false }),
ENABLE_CACHE: bool({ default: true }),
});Network Validators
email(options?)
Validates email addresses.
import { email } from 'envguard';
const env = cleanEnv({
ADMIN_EMAIL: email(),
SUPPORT_EMAIL: email({ default: '[email protected]' }),
});url(options?)
Validates URLs with http/https protocol.
import { url } from 'envguard';
const env = cleanEnv({
API_URL: url(),
WEBHOOK_URL: url({ default: 'https://example.com/webhook' }),
});host(options?)
Validates hostnames or IP addresses (IPv4 and IPv6).
import { host } from 'envguard';
const env = cleanEnv({
DB_HOST: host({ default: 'localhost' }),
REDIS_HOST: host(),
});port(options?)
Validates TCP port numbers (1-65535).
import { port } from 'envguard';
const env = cleanEnv({
PORT: port({ default: 3000 }),
// Custom range
ADMIN_PORT: port({ min: 1024, max: 49151 }),
});Data Validators
json<T>(options?)
Parses JSON values.
import { json } from 'envguard';
const env = cleanEnv({
CONFIG: json<{ key: string }>(),
// With schema validation
SETTINGS: json<Settings>({
schema: (v): v is Settings =>
typeof v === 'object' && v !== null && 'name' in v,
}),
});array<T>(options?)
Parses comma-separated values into arrays.
import { array, num } from 'envguard';
const env = cleanEnv({
// String array
ALLOWED_HOSTS: array({ default: ['localhost'] }),
// Custom separator
TAGS: array({ separator: '|' }),
// With item validation
PORTS: array({ itemValidator: num() }),
// With constraints
IDS: array({
minItems: 1,
maxItems: 10,
unique: true,
}),
});uuid(options?)
Validates UUID strings.
import { uuid } from 'envguard';
const env = cleanEnv({
SESSION_ID: uuid(),
TENANT_ID: uuid({ default: '00000000-0000-0000-0000-000000000000' }),
});Special Validators
enums(options)
Validates against a list of allowed values with proper TypeScript inference.
import { enums } from 'envguard';
const env = cleanEnv({
LOG_LEVEL: enums({
values: ['debug', 'info', 'warn', 'error'] as const,
default: 'info',
}),
});
// env.LOG_LEVEL is typed as 'debug' | 'info' | 'warn' | 'error'regex(options)
Validates against a custom regular expression.
import { regex } from 'envguard';
const env = cleanEnv({
LICENSE_KEY: regex({
pattern: /^[A-Z]{3}-\d{4}-[A-Z]{3}$/,
desc: 'License key in format XXX-0000-XXX',
}),
});duration(options?)
Parses duration strings (e.g., 100ms, 5s, 2m, 1h, 7d).
import { duration } from 'envguard';
const env = cleanEnv({
// Returns milliseconds by default
TIMEOUT: duration({ default: 5000 }),
// Convert to seconds
CACHE_TTL: duration({ unit: 's' }),
});
// TIMEOUT=30s -> 30000 (ms)
// CACHE_TTL=5m -> 300 (s)bytes(options?)
Parses byte size strings (e.g., 100B, 5KB, 2MB, 1GB).
import { bytes } from 'envguard';
const env = cleanEnv({
// Returns bytes by default
MAX_FILE_SIZE: bytes({ default: 10485760 }), // 10MB
// Convert to megabytes
MEMORY_LIMIT: bytes({ unit: 'MB' }),
});
// MAX_FILE_SIZE=50MB -> 52428800 (bytes)
// MEMORY_LIMIT=2GB -> 2048 (MB)Advanced Features
Default Values
EnvGuard supports multiple types of default values:
const env = cleanEnv({
// Always use this default
PORT: num({ default: 3000 }),
// Only in non-production environments
DEBUG: bool({ devDefault: true }),
// Only in test environment
DB_URL: str({ testDefault: 'sqlite::memory:' }),
});Secret Masking
Mark sensitive variables to mask their values in error messages:
const env = cleanEnv({
API_KEY: str({ secret: true }),
DATABASE_PASSWORD: str({ secret: true }),
});
// Error messages will show: "API_KEY: supe**********d123"Conditional Requirements
Make variables required based on other values:
const env = cleanEnv({
USE_REDIS: bool({ default: false }),
REDIS_URL: str({
requiredWhen: (env) => env.USE_REDIS === true,
default: undefined,
}),
});Warning Mode
Use warnOnly for non-critical variables that shouldn't block startup:
const env = cleanEnv({
ANALYTICS_KEY: str({
warnOnly: true,
desc: 'Optional analytics tracking key',
}),
});Extra Variable Detection
Detect unknown environment variables:
const env = cleanEnv(
{ PORT: num() },
{
// Warn about extra variables
warnOnExtra: true,
// Or throw an error
strict: true,
// Allow specific extra variables
allowedExtra: ['CUSTOM_VAR'],
}
);Custom Validators
Create your own validators:
import { makeValidator, EnvValidationError } from 'envguard';
const hexColor = makeValidator<string>((value, key) => {
if (!/^#[0-9A-Fa-f]{6}$/.test(value)) {
throw new EnvValidationError(key, 'must be a valid hex color', value);
}
return value.toLowerCase();
});
const env = cleanEnv({
PRIMARY_COLOR: hexColor({ default: '#000000' }),
ACCENT_COLOR: hexColor(),
});Custom Middleware
Transform the validated environment:
import { customCleanEnv, str, num } from 'envguard';
const env = customCleanEnv(
{
DB_HOST: str({ default: 'localhost' }),
DB_PORT: num({ default: 5432 }),
DB_NAME: str(),
},
(env) => ({
...env,
connectionString: `postgres://${env.DB_HOST}:${env.DB_PORT}/${env.DB_NAME}`,
})
);
console.log(env.connectionString);Utility Functions
Group by Prefix
import { cleanEnv, str, num, groupByPrefix } from 'envguard';
const env = cleanEnv({
DB_HOST: str({ default: 'localhost' }),
DB_PORT: num({ default: 5432 }),
DB_NAME: str({ default: 'mydb' }),
CACHE_HOST: str({ default: 'localhost' }),
});
const dbConfig = groupByPrefix(env, 'DB');
// { host: 'localhost', port: 5432, name: 'mydb' }Generate .env.example
import { writeEnvExample, str, num, bool } from 'envguard';
const spec = {
PORT: num({ default: 3000, desc: 'Server port' }),
HOST: str({ desc: 'Server host', example: 'localhost' }),
DEBUG: bool({ default: false, desc: 'Enable debug mode' }),
API_KEY: str({ desc: 'API key for external service', secret: true }),
};
writeEnvExample(spec, {
outputPath: '.env.example',
includeDescriptions: true,
includeExamples: true,
groupByPrefix: true,
});Output:
# Server port
PORT=3000
# Server host
HOST=localhost
# Enable debug mode
DEBUG=false
# API key for external service
API_KEY= # RequiredCustom Reporter
Override error handling:
import { cleanEnv, str } from 'envguard';
const env = cleanEnv(
{ API_KEY: str() },
{
reporter: {
onError: (errors) => {
// Custom error handling
console.error('Config errors:', errors);
process.exit(1);
},
onWarning: (warnings) => {
// Custom warning handling
console.warn('Config warnings:', warnings);
},
},
}
);API Reference
cleanEnv(spec, options?)
Main validation function.
Options:
env: Custom environment object (default:process.env)reporter: Custom error reporterstrict: Throw on unknown variables (default:false)warnOnExtra: Warn on unknown variables (default:false)allowedExtra: Array of allowed extra variable names
Validator Options
All validators accept these common options:
default: Default value when variable is missingdevDefault: Default for non-production environmentstestDefault: Default for test environment onlychoices: Array of allowed valuesdesc: Description for documentationexample: Example value for .env.exampledocs: URL to documentationsecret: Mask value in error messagesdeprecated: Deprecation warning messagerequiredWhen: Function to determine if requiredwarnOnly: Don't fail on validation errors
License
MIT
