npm package: @spidy29/env-guardian
Description: Zero-dependency environment variable validator with automatic type safety and runtime validation
Author: Arjun Sharma
Latest version: 1.0.0

# 🛡️ 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

```bash
npm install env-guardian
```

## 🚀 Quick Start

```typescript
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

```typescript
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`

```typescript
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).

```typescript
const config = validateEnv({
  ENABLE_DEBUG: env.boolean({ 
    default: false 
  })
});
```

#### `env.enum(values, options?)`

Validates against a list of allowed values.

```typescript
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']`)

```typescript
const config = validateEnv({
  DATABASE_URL: env.url({ 
    protocols: ['postgres', 'postgresql'] 
  }),
  API_URL: env.url()
});
```

#### `env.email(options?)`

Validates email format.

```typescript
const config = validateEnv({
  ADMIN_EMAIL: env.email()
});
```

#### `env.json(options?)`

Parses and validates JSON strings.

```typescript
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

```typescript
const config = validateEnv({
  ALLOWED_ORIGINS: env.array({ 
    separator: ',',
    minItems: 1 
  }),
  TAGS: env.array()
});
```

## 🎨 Usage Examples

### Basic Web Server

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
// 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:

```typescript
// 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:

```typescript
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!