DSL Syntax

Learn the simple, powerful DSL for defining your environment schema.

Syntax Format

type:modifier1:modifier2:modifier3

Modifiers are separated by colons (:).

Types

string

String value. Returns a string type.

env({
  API_KEY: "string",
  LOG_LEVEL: "string:default=info",
});

number

Number value. Automatically coerced from string. Returns a number type.

env({
  PORT: "number",
  TIMEOUT: "number:default=5000",
  // PORT from process.env will be coerced: "3000" → 3000
});

enum

Enum with specific values. Returns a union type of the allowed values.

env({
  NODE_ENV: "enum:development,production,test",
  MODE: "enum:dev,prod,staging:default=dev",
});

// TypeScript infers:
// ENV.NODE_ENV: "development" | "production" | "test"
// ENV.MODE: "dev" | "prod" | "staging"

Modifiers

url

Applies to: string

Validates that the string is a valid URL format.

env({
  API_URL: "string:url",
  DATABASE_URL: "string:url",
});

// Validates: https://api.example.com ✅
// Rejects: not-a-url ❌

min=N

Applies to: string, number

For strings: minimum length. For numbers: minimum value.

env({
  API_KEY: "string:min=20",      // Minimum 20 characters
  TIMEOUT: "number:min=1000",    // Minimum value 1000
  JWT_SECRET: "string:min=32:secret",
});

default=value

Applies to: All types

Default value if the environment variable is not provided.

env({
  PORT: "number:default=3000",
  LOG_LEVEL: "string:default=info",
  MODE: "enum:dev,prod:default=dev",
});

// If PORT is not set, it defaults to 3000
// If LOG_LEVEL is not set, it defaults to "info"

secret

Applies to: All types

Marks the value as secret. It will be masked in error messages (only length shown).

env({
  JWT_SECRET: "string:min=32:secret",
  API_KEY: "string:secret",
  DATABASE_URL: "string:url:secret",
});

// In error messages:
// JWT_SECRET: [REDACTED (length: 12)]
// Never exposes the actual value!

Combining Modifiers

You can combine multiple modifiers:

env({
  // String with URL validation, minimum length, and secret masking
  DATABASE_URL: "string:url:min=10:secret",
  
  // Number with minimum value and default
  TIMEOUT: "number:min=1000:default=5000",
  
  // Enum with default value
  MODE: "enum:dev,prod,staging:default=dev",
  
  // String with minimum length, default, and secret
  API_KEY: "string:min=20:default=default-key:secret",
});

Complete Examples

import { env } from "@liahus/safe-env";

const ENV = env({
  // Basic types
  API_KEY: "string",
  PORT: "number",
  
  // With validation
  DATABASE_URL: "string:url",
  JWT_SECRET: "string:min=32:secret",
  
  // With defaults
  LOG_LEVEL: "string:default=info",
  TIMEOUT: "number:default=5000",
  
  // Enums
  NODE_ENV: "enum:development,production,test",
  MODE: "enum:dev,prod:default=dev",
  
  // Complex combinations
  API_URL: "string:url:default=https://api.example.com",
  MAX_RETRIES: "number:min=1:default=3",
});

⚠️ Important Note

URLs with :// in default values need special handling because : is used as a separator. Consider providing the URL via environment variable instead of using a default.