EnvGuard

A type-safe environment variable validation and management library for Node.js. EnvGuard helps you validate, parse, and manage environment variables with a simple schema-based approach.

Features

Installation

npm i @osmn-byhn/envguard

Quick Start

import { loadEnv } from '@osmn-byhn/envguard';

const schema = {
  PORT: "number",
  DATABASE_URL: "string",
  DEBUG: "boolean",
};

const env = loadEnv(schema);

console.log(env.PORT); // 3000 (number)
console.log(env.DATABASE_URL); // "postgresql://..." (string)
console.log(env.DEBUG); // true (boolean)

Documentation

Basic Usage

import { loadEnv } from '@osmn-byhn/envguard';
import { EnvSchema } from '@osmn-byhn/envguard';

const schema: EnvSchema = {
  PORT: "number",
  DATABASE_URL: "string",
};

const env = loadEnv(schema);

Type System

EnvGuard supports multiple types for environment variable validation:

1. String Type

Basic string validation. Use "string" for required strings, or "string?" for optional strings.
const schema = {
  API_KEY: "string",      // Required
  OPTIONAL_KEY: "string?", // Optional
};

// .env
// API_KEY=my-secret-key
// OPTIONAL_KEY=optional-value (or omit this line)
Example:
const env = loadEnv(schema);
console.log(env.API_KEY); // "my-secret-key" (string)
console.log(env.OPTIONAL_KEY); // "optional-value" or undefined

2. Number Type

Validates and converts string values to numbers.
const schema = {
  PORT: "number",
  TIMEOUT: "number?",
};

// .env
// PORT=3000
// TIMEOUT=5000
Example:
const env = loadEnv(schema);
console.log(env.PORT); // 3000 (number, not string)
console.log(typeof env.PORT); // "number"
Error cases:

3. Boolean Type

Converts string values to boolean. Accepts "true", "1" (case-insensitive) as true, everything else as false.
const schema = {
  DEBUG: "boolean",
  ENABLE_FEATURE: "boolean?",
};

// .env
// DEBUG=true
// ENABLE_FEATURE=1
Example:
const env = loadEnv(schema);
console.log(env.DEBUG); // true (boolean)
console.log(env.ENABLE_FEATURE); // true (boolean)
Accepted values:

4. URL Type

Validates that the value is a valid URL.
const schema = {
  API_BASE_URL: "url",
  WEBHOOK_URL: "url?",
};

// .env
// API_BASE_URL=https://api.example.com
// WEBHOOK_URL=https://webhook.example.com/callback
Example:
const env = loadEnv(schema);
console.log(env.API_BASE_URL); // "https://api.example.com"
Error cases:

5. Email Type

Validates that the value is a valid email address.
const schema = {
  ADMIN_EMAIL: "email",
  SUPPORT_EMAIL: "email?",
};

// .env
// [email protected]
// [email protected]
Example:
const env = loadEnv(schema);
console.log(env.ADMIN_EMAIL); // "[email protected]"
Error cases:

6. Enum Type

Restricts values to a specific set of allowed strings.
const schema = {
  NODE_ENV: ["development", "production", "test"],
  LOG_LEVEL: ["debug", "info", "warn", "error"],
};

// .env
// NODE_ENV=production
// LOG_LEVEL=info
Example:
const env = loadEnv(schema);
console.log(env.NODE_ENV); // "production"
console.log(env.LOG_LEVEL); // "info"
Error cases:

7. JSON Type

Parses and validates JSON strings.
const schema = {
  CONFIG: "json",
  FEATURE_FLAGS: "json?",
};

// .env
// CONFIG={"timeout":5000,"retries":3}
// FEATURE_FLAGS={"feature1":true,"feature2":false}
Example:
const env = loadEnv(schema);
console.log(env.CONFIG); // { timeout: 5000, retries: 3 } (object)
console.log(env.FEATURE_FLAGS); // { feature1: true, feature2: false } (object)
Error cases:

8. Array Type

Parses comma-separated values into an array.
const schema = {
  ALLOWED_ORIGINS: "array",
  FEATURES: "array?",
};

// .env
// ALLOWED_ORIGINS=http://localhost:3000,https://example.com,https://app.example.com
// FEATURES=feature1,feature2,feature3
Example:
const env = loadEnv(schema);
console.log(env.ALLOWED_ORIGINS); // ["http://localhost:3000", "https://example.com", "https://app.example.com"]
console.log(env.FEATURES); // ["feature1", "feature2", "feature3"]
Note: Values are automatically trimmed of whitespace.

9. Date Type

Parses and validates date strings.
const schema = {
  START_DATE: "date",
  END_DATE: "date?",
};

// .env
// START_DATE=2024-01-01
// END_DATE=2024-12-31
Example:
const env = loadEnv(schema);
console.log(env.START_DATE); // Date object: 2024-01-01T00:00:00.000Z
console.log(env.START_DATE instanceof Date); // true
Error cases:

10. Custom Type

Advanced validation with custom patterns, default values, and error handling.
const schema = {
  SECRET_TOKEN: {
    type: "string",
    pattern: /^[A-Za-z0-9]{32,}$/,
    description: "32 characters or longer alphanumeric token",
    error: (err) => {
      console.error("Custom error handler:", err.message);
      process.exit(1);
    },
    required: true,
  },
  LOG_LEVEL: {
    type: ["debug", "info", "warn", "error"],
    default: "info",
    description: "Log level",
    error: (err) => console.error(err),
  },
  API_VERSION: {
    type: "string",
    pattern: /^v\d+\.\d+\.\d+$/,
    default: "v1.0.0",
    description: "API version in semver format",
  },
};

// .env
// SECRET_TOKEN=MySuperSecretToken12345678901234567890
// LOG_LEVEL=debug (or omit for default "info")
// API_VERSION=v2.1.0
Custom Type Options: Example:
const env = loadEnv(schema);
console.log(env.SECRET_TOKEN); // "MySuperSecretToken12345678901234567890"
console.log(env.LOG_LEVEL); // "debug" or "info" (default)
console.log(env.API_VERSION); // "v2.1.0"
Error cases:

Options

The loadEnv function accepts an optional second parameter with configuration options:
const env = loadEnv(schema, {
  path: ".env",           // Path to .env file (default: ".env")
  strict: true,          // Warn about unknown variables (default: false)
  example: true,        // Generate .env.example file (default: false)
  error: (err) => {     // Custom error handler
    console.error(err.message);
    process.exit(1);
  },
  debug: true,          // Enable debug mode (default: false)
});

Options Reference

Option Type Default Description
path string ".env" Path to the environment file
strict boolean false If true, warns about variables in .env that are not in the schema
example boolean false If true, generates a .env.example file with all schema keys
error (error: Error) => void undefined Custom error handler function
debug boolean false Enable debug logging

Error Handling

EnvGuard throws errors when validation fails. You can handle them with try-catch or use the error callback:
// Method 1: Try-catch
try {
  const env = loadEnv(schema);
} catch (error) {
  console.error("Validation failed:", error.message);
  process.exit(1);
}

// Method 2: Error callback
const env = loadEnv(schema, {
  error: (err) => {
    console.error("Validation failed:", err.message);
    process.exit(1);
  },
});
Common Errors:

Security Features

EnvGuard automatically masks sensitive values when accessed through the returned object:
const schema = {
  SECRET_TOKEN: "string",
  API_KEY: "string",
  DATABASE_PASSWORD: "string",
};

const env = loadEnv(schema);

// .env
// SECRET_TOKEN=my-secret
// API_KEY=my-key
// DATABASE_PASSWORD=my-password

console.log(env.SECRET_TOKEN); // "[HIDDEN]"
console.log(env.API_KEY); // "[HIDDEN]"
console.log(env.DATABASE_PASSWORD); // "[HIDDEN]"
Note: Variables containing "SECRET" or "TOKEN" in their names are automatically masked.

Generating .env.example

You can automatically generate a .env.example file:
const env = loadEnv(schema, {
  example: true,
});
This creates a .env.example file with all schema keys (without values):
DATABASE_URL=
PORT=
DEBUG=
API_BASE_URL=

Strict Mode

Enable strict mode to get warnings about unknown variables in your .env file:
const env = loadEnv(schema, {
  strict: true,
});

// If .env contains variables not in schema:
// [EnvGuard] Unknown env variables: UNKNOWN_VAR, ANOTHER_UNKNOWN

Complete Example

import { loadEnv } from '@osmn-byhn/envguard';
import { EnvSchema } from '@osmn-byhn/envguard';

const schema: EnvSchema = {
  // Required variables
  DATABASE_URL: "string",
  PORT: "number",
  DEBUG: "boolean",
  API_BASE_URL: "url",
  ADMIN_EMAIL: "email",
  NODE_ENV: ["development", "production", "test"],
  
  // Optional variables
  API_KEY: "string?",
  TIMEOUT: "number?",
  
  // Complex types
  CONFIG: "json",
  ALLOWED_ORIGINS: "array",
  START_DATE: "date",
  
  // Custom validation
  SECRET_TOKEN: {
    type: "string",
    pattern: /^[A-Za-z0-9]{32,}$/,
    required: true,
  },
  LOG_LEVEL: {
    type: ["debug", "info", "warn", "error"],
    default: "info",
  },
};

const env = loadEnv(schema, {
  strict: true,
  example: true,
  error: (err) => {
    console.error("❌ Environment validation failed:", err.message);
    process.exit(1);
  },
});

// Use validated environment variables
console.log(Server starting on port ${env.PORT});
console.log(Database: ${env.DATABASE_URL});
console.log(Environment: ${env.NODE_ENV});

TypeScript Support

EnvGuard is written in TypeScript and provides full type definitions:
import { loadEnv, EnvSchema, ParsedEnv } from '@osmn-byhn/envguard';

const schema: EnvSchema = {
  PORT: "number",
  DATABASE_URL: "string",
};

const env: ParsedEnv = loadEnv(schema);
// env is fully typed!

Best Practices

Contributing

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

License

MIT

Changelog

0.1.0

Author: Osman Beyhan


❤️ Make via MDtoWeb