env-exists
v1.0.0
Published
Check if environment variables exist and have values. Simple validation for required env vars.
Downloads
2
Maintainers
Readme
env-exists
Check if environment variables exist and have values. Simple validation for required env vars with powerful features.
Why env-exists?
Environment variable validation shouldn't be complicated:
- ✅ Simple API: One function call to validate env vars
- ✅ Flexible validation: Required, optional, type checking, custom rules
- ✅ Clear error messages: Know exactly what's missing or invalid
- ✅ TypeScript support: Full type definitions included
- ✅ Zero dependencies: Lightweight and fast
- ✅ Comprehensive: From basic checks to complex validation schemas
Installation
npm install env-existsQuick Start
const envExists = require('env-exists');
// Basic validation - throws on failure
envExists(['API_KEY', 'DATABASE_URL']); // boolean or throws
// Check single variable
envExists('PORT'); // boolean or throws
// Get detailed results without throwing
const result = envExists(['API_KEY', 'PORT'], { throw: false });
console.log(result);
// {
// valid: false,
// missing: ['API_KEY'],
// empty: [],
// found: ['PORT'],
// values: { PORT: '3000' }
// }API Reference
envExists(vars, options?)
Main function to check if environment variables exist.
Parameters:
vars(string | string[]): Variable name(s) to checkoptions(object, optional): Configuration options
Options:
throw(boolean): Throw error on validation failure (default: true)nonEmpty(boolean): Require non-empty values (default: true)all(boolean): All variables must exist vs any (default: true)defaults(object): Default values for missing variablesallowEmpty(string[]): Variables that can be empty
Returns: boolean (when throw=true) or ValidationResult object (when throw=false)
const envExists = require('env-exists');
// Basic usage - throws on failure
envExists(['API_KEY', 'DATABASE_URL']); // true or throws
// Don't throw, get details
const result = envExists(['VAR1', 'VAR2'], { throw: false });
// Allow empty values for specific vars
envExists(['API_KEY', 'DEBUG'], { allowEmpty: ['DEBUG'] });
// Provide defaults
envExists(['PORT', 'HOST'], {
defaults: { PORT: '3000', HOST: 'localhost' }
});
// "Any" mode - at least one must exist
envExists(['REDIS_URL', 'MEMCACHE_URL'], { all: false });Helper Functions
envExistsOrThrow(vars, options?)
Always throws on failure (explicit behavior).
const { envExistsOrThrow } = require('env-exists');
envExistsOrThrow(['API_KEY', 'SECRET']); // true or throwsenvExistsDetails(vars, options?)
Never throws, always returns detailed results.
const { envExistsDetails } = require('env-exists');
const result = envExistsDetails(['API_KEY', 'PORT']);
console.log(result.missing); // ['API_KEY']
console.log(result.values); // { PORT: '3000' }envExistsAll(vars, options?) / envExistsAny(vars, options?)
Explicit "all" vs "any" validation.
const { envExistsAll, envExistsAny } = require('env-exists');
envExistsAll(['VAR1', 'VAR2']); // Both must exist
envExistsAny(['VAR1', 'VAR2']); // At least one must existenvExistsWithValues(varMap, options?)
Check for specific values.
const { envExistsWithValues } = require('env-exists');
// Exact values
envExistsWithValues({
NODE_ENV: 'production',
DEBUG: 'false'
});
// Multiple allowed values
envExistsWithValues({
LOG_LEVEL: ['debug', 'info', 'warn', 'error'],
NODE_ENV: ['development', 'production']
});envExistsNonEmpty(vars, options?)
Explicit non-empty validation.
const { envExistsNonEmpty } = require('env-exists');
envExistsNonEmpty(['API_KEY', 'SECRET']); // Must exist and be non-emptyAdvanced Functions
envGet(varName, options?)
Get single environment variable with validation and type conversion.
const { envGet } = require('env-exists');
// Basic usage
const port = envGet('PORT', { default: 3000, type: 'number' });
// Type conversion
const debug = envGet('DEBUG', { type: 'boolean', default: false });
const config = envGet('CONFIG', { type: 'json', required: false });
// Custom validation
const apiKey = envGet('API_KEY', {
validate: /^sk-[a-zA-Z0-9]{32}$/,
required: true
});
// Function validator
const port = envGet('PORT', {
type: 'number',
validate: (val) => val > 0 && val < 65536 || 'Port must be 1-65535'
});envValidate(schema)
Validate multiple variables with detailed schema.
const { envValidate } = require('env-exists');
const config = envValidate({
PORT: { type: 'number', default: 3000 },
DEBUG: { type: 'boolean', default: false },
API_KEY: { required: true, validate: /^sk-/ },
DATABASE_URL: { required: true },
REDIS_URL: { required: false },
MAX_CONNECTIONS: {
type: 'number',
default: 10,
validate: (val) => val > 0 || 'Must be positive'
}
});
console.log(config);
// {
// PORT: 3000,
// DEBUG: false,
// API_KEY: 'sk-abc123...',
// DATABASE_URL: 'postgres://...',
// REDIS_URL: undefined,
// MAX_CONNECTIONS: 10
// }Utility Functions
envLoad(filePath?, options?)
Load environment variables from .env file.
const { envLoad } = require('env-exists');
// Load from .env file
const loaded = envLoad();
// Load from custom file
const loaded = envLoad('.env.production');
// Override existing variables
const loaded = envLoad('.env', { override: true });
console.log(loaded); // { API_KEY: 'abc123', PORT: '3000' }envSummary(vars?)
Get summary of environment variables.
const { envSummary } = require('env-exists');
// Summary of all env vars
const summary = envSummary();
// Summary of specific vars
const summary = envSummary(['API_KEY', 'PORT', 'DEBUG']);
console.log(summary);
// {
// total: 3,
// defined: 2,
// empty: 0,
// missing: 1,
// variables: {
// API_KEY: { status: 'missing' },
// PORT: { status: 'defined', value: '3000', length: 4 },
// DEBUG: { status: 'defined', value: 'true', length: 4 }
// }
// }envAssert(vars, message?)
Testing helper that throws AssertionError.
const { envAssert } = require('env-exists');
// In tests
envAssert(['API_KEY'], 'API_KEY is required for tests');Usage Examples
Application Startup Validation
const envExists = require('env-exists');
function validateEnvironment() {
try {
// Required for all environments
envExists(['NODE_ENV', 'PORT']);
// Production requirements
if (process.env.NODE_ENV === 'production') {
envExists([
'API_KEY',
'DATABASE_URL',
'REDIS_URL',
'SESSION_SECRET'
]);
}
// Development optional
if (process.env.NODE_ENV === 'development') {
envExists(['DEBUG'], { defaults: { DEBUG: 'true' } });
}
console.log('✅ Environment validation passed');
} catch (error) {
console.error('❌ Environment validation failed:', error.message);
process.exit(1);
}
}
validateEnvironment();Configuration Object Creation
const { envValidate } = require('env-exists');
const config = envValidate({
// Server configuration
PORT: { type: 'number', default: 3000 },
HOST: { default: '0.0.0.0' },
// Database
DATABASE_URL: { required: true },
DB_POOL_SIZE: { type: 'number', default: 10 },
// Redis (optional)
REDIS_URL: { required: false },
// Security
SESSION_SECRET: {
required: true,
validate: (val) => val.length >= 32 || 'Session secret must be at least 32 characters'
},
// Feature flags
ENABLE_LOGGING: { type: 'boolean', default: true },
LOG_LEVEL: {
default: 'info',
validate: (val) => ['debug', 'info', 'warn', 'error'].includes(val) || 'Invalid log level'
},
// External services
STRIPE_KEY: { validate: /^sk_/ },
SENDGRID_API_KEY: { validate: /^SG\./ }
});
module.exports = config;Environment-Specific Validation
const { envExistsAny, envExistsWithValues } = require('env-exists');
// Must have at least one cache solution
envExistsAny(['REDIS_URL', 'MEMCACHE_URL'], {
throw: true
});
// Validate environment matches expected values
envExistsWithValues({
NODE_ENV: ['development', 'staging', 'production'],
LOG_LEVEL: ['debug', 'info', 'warn', 'error']
});
// Database validation
if (process.env.NODE_ENV === 'production') {
envExistsWithValues({
DB_SSL: 'true',
DB_SSL_REJECT_UNAUTHORIZED: 'true'
});
}Microservice Configuration
const { envGet, envExists } = require('env-exists');
class ServiceConfig {
constructor() {
// Validate required variables exist
envExists([
'SERVICE_NAME',
'SERVICE_VERSION',
'PORT'
]);
// Parse configuration with defaults and validation
this.serviceName = envGet('SERVICE_NAME');
this.version = envGet('SERVICE_VERSION');
this.port = envGet('PORT', { type: 'number', default: 3000 });
// Optional configuration
this.logLevel = envGet('LOG_LEVEL', { default: 'info' });
this.enableMetrics = envGet('ENABLE_METRICS', { type: 'boolean', default: true });
// Database configuration
this.database = {
url: envGet('DATABASE_URL'),
poolSize: envGet('DB_POOL_SIZE', { type: 'number', default: 10 }),
timeout: envGet('DB_TIMEOUT', { type: 'number', default: 30000 })
};
// External service URLs
this.services = {
auth: envGet('AUTH_SERVICE_URL', { validate: /^https?:\/\// }),
payments: envGet('PAYMENT_SERVICE_URL', { required: false })
};
}
validate() {
// Additional business logic validation
if (this.port < 1024 && process.getuid?.() !== 0) {
throw new Error('Cannot bind to privileged port without root access');
}
return this;
}
}
const config = new ServiceConfig().validate();Testing Setup
const { envAssert, envLoad, envSummary } = require('env-exists');
describe('Environment Tests', () => {
beforeAll(() => {
// Load test environment
envLoad('.env.test');
// Assert required test variables
envAssert([
'TEST_DATABASE_URL',
'TEST_API_KEY'
], 'Missing required test environment variables');
});
test('should have all required environment variables', () => {
const summary = envSummary([
'NODE_ENV',
'TEST_DATABASE_URL',
'TEST_API_KEY'
]);
expect(summary.missing).toBe(0);
expect(summary.defined).toBe(3);
});
});Docker Environment Validation
const { envExists, envGet } = require('env-exists');
// Validate Docker secrets are mounted
const secrets = [
'DB_PASSWORD_FILE',
'API_KEY_FILE',
'SSL_CERT_FILE'
].map(fileVar => {
const filePath = envGet(fileVar);
const fs = require('fs');
if (!fs.existsSync(filePath)) {
throw new Error(`Secret file not found: ${filePath} (from ${fileVar})`);
}
return {
var: fileVar,
path: filePath,
content: fs.readFileSync(filePath, 'utf8').trim()
};
});
console.log('✅ All Docker secrets loaded successfully');CLI Tool Configuration
#!/usr/bin/env node
const { envLoad, envExists, envSummary } = require('env-exists');
// Load environment from multiple sources
envLoad('.env');
envLoad('.env.local', { override: true });
// CLI-specific validation
try {
envExists(['CLI_API_KEY'], {
defaults: { CLI_API_KEY: process.env.API_KEY } // Fallback to general API key
});
} catch (error) {
console.error('❌ Configuration Error:');
console.error(error.message);
console.error('\nTo fix this:');
console.error(' 1. Set CLI_API_KEY environment variable');
console.error(' 2. Or create .env file with CLI_API_KEY=your_key');
console.error(' 3. Or set API_KEY as fallback');
process.exit(1);
}
// Show configuration summary
if (process.argv.includes('--debug')) {
const summary = envSummary(['CLI_API_KEY', 'DEBUG', 'LOG_LEVEL']);
console.log('Environment Summary:', summary);
}Error Messages
Clear, actionable error messages help debug configuration issues:
// Missing variables
// Error: Environment validation failed (all mode): Missing: API_KEY, DATABASE_URL
// Empty variables
// Error: Environment validation failed (all mode): Empty: API_KEY
// Type validation
// Error: PORT type conversion failed: PORT must be a valid number, got: abc
// Custom validation
// Error: API_KEY does not match pattern: /^sk-/
// Schema validation
// Error: Environment validation failed:
// - Missing: DATABASE_URL
// - PORT type conversion failed: PORT must be a valid number, got: abc
// - API_KEY does not match pattern: /^sk-/TypeScript Usage
import envExists, {
EnvExistsOptions,
envValidate,
envGet
} from 'env-exists';
// Basic validation
const isValid: boolean = envExists(['API_KEY', 'PORT']);
// With options
const options: EnvExistsOptions = {
throw: false,
nonEmpty: true,
defaults: { PORT: '3000' }
};
const result = envExists(['API_KEY'], options);
// Schema validation
const config = envValidate({
PORT: { type: 'number', default: 3000 },
DEBUG: { type: 'boolean', default: false }
});
// Type-safe environment variables
const port: number = envGet('PORT', { type: 'number', default: 3000 });
const debug: boolean = envGet('DEBUG', { type: 'boolean', default: false });Best Practices
- Validate early: Check environment variables at application startup
- Use schemas: For complex apps, use
envValidate()with a schema - Provide defaults: Use sensible defaults for non-critical variables
- Clear errors: Let
env-existsgenerate clear error messages - Environment-specific: Different validation for dev/staging/production
- Document requirements: List required env vars in your README
Comparison with Alternatives
| Feature | env-exists | dotenv | envalid | joi | |---------|------------|---------|---------|-----| | Simple API | ✅ | ❌ | ✅ | ❌ | | Type validation | ✅ | ❌ | ✅ | ✅ | | Custom validation | ✅ | ❌ | ✅ | ✅ | | Clear errors | ✅ | ❌ | ✅ | ✅ | | Zero dependencies | ✅ | ✅ | ❌ | ❌ | | TypeScript support | ✅ | ✅ | ✅ | ✅ | | File loading | ✅ | ✅ | ❌ | ❌ |
License
MIT License. See LICENSE file for details.
Contributing
Pull requests welcome! Please ensure tests pass:
npm test