Examples

Real-world examples for different frameworks and use cases.

Next.js (App Router)

Next.js App Router
// app/config/env.ts
import { env } from "@liahus/safe-env";

export const ENV = env({
  DATABASE_URL: "string:url",
  NEXTAUTH_SECRET: "string:min=32:secret",
  NEXTAUTH_URL: "string:url",
  NODE_ENV: "enum:development,production,test",
});

// Use it anywhere in your app
// app/api/users/route.ts
import { ENV } from "@/app/config/env";

export async function GET() {
  // ENV is fully typed!
  const dbUrl = ENV.DATABASE_URL;
  // ...
}

Next.js (Pages Router)

Next.js Pages Router
// lib/env.ts
import { env } from "@liahus/safe-env";

export const ENV = env({
  DATABASE_URL: "string:url",
  API_KEY: "string:min=20:secret",
  NODE_ENV: "enum:development,production,test",
});

// Use in pages or API routes
// pages/api/hello.ts
import { ENV } from "@/lib/env";

export default function handler(req, res) {
  res.json({ env: ENV.NODE_ENV });
}

Express

Express
// config/env.ts
import { env } from "@liahus/safe-env";

export const ENV = env({
  PORT: "number:default=3000",
  DATABASE_URL: "string:url",
  JWT_SECRET: "string:min=32:secret",
  NODE_ENV: "enum:development,production,test",
});

// server.ts
import express from "express";
import { ENV } from "./config/env";

const app = express();

app.listen(ENV.PORT, () => {
  console.log(`Server running on port ${ENV.PORT}`);
  console.log(`Environment: ${ENV.NODE_ENV}`);
});

Fastify

Fastify
// config/env.ts
import { env } from "@liahus/safe-env";

export const ENV = env({
  PORT: "number:default=3000",
  HOST: "string:default=0.0.0.0",
  DATABASE_URL: "string:url",
  JWT_SECRET: "string:min=32:secret",
});

// server.ts
import Fastify from "fastify";
import { ENV } from "./config/env";

const fastify = Fastify({ logger: true });

fastify.listen({ port: ENV.PORT, host: ENV.HOST }, (err) => {
  if (err) {
    fastify.log.error(err);
    process.exit(1);
  }
});

NestJS

NestJS
// src/config/env.config.ts
import { env } from "@liahus/safe-env";

export const ENV = env({
  PORT: "number:default=3000",
  DATABASE_URL: "string:url",
  JWT_SECRET: "string:min=32:secret",
  NODE_ENV: "enum:development,production,test",
});

// Use in modules
// src/app.module.ts
import { Module } from "@nestjs/common";
import { ENV } from "./config/env.config";

@Module({
  // ...
})
export class AppModule {
  constructor() {
    console.log(`Server running on port ${ENV.PORT}`);
  }
}

Testing

Testing
// tests/setup.ts
import { env } from "@liahus/safe-env";

// Create test environment
export const testEnv = env(
  {
    DATABASE_URL: "string:url",
    API_KEY: "string:min=10",
    PORT: "number:default=3000",
  },
  {
    env: {
      DATABASE_URL: "https://test-db.example.com",
      API_KEY: "test-api-key-12345",
      PORT: "8080",
    },
  }
);

// Use in tests
// tests/api.test.ts
import { testEnv } from "./setup";

describe("API", () => {
  it("should use test environment", () => {
    expect(testEnv.DATABASE_URL).toBe("https://test-db.example.com");
    expect(testEnv.PORT).toBe(8080);
  });
});

With dotenv

With dotenv
// Load .env file first
import "dotenv/config";
import { env } from "@liahus/safe-env";

// Now process.env is populated from .env file
export const ENV = env({
  DATABASE_URL: "string:url",
  PORT: "number:default=3000",
  JWT_SECRET: "string:min=32:secret",
});

// .env file:
// DATABASE_URL=https://db.example.com
// PORT=3000
// JWT_SECRET=your-secret-key-here

Complex Schema

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

const ENV = env({
  // Database
  DATABASE_URL: "string:url:secret",
  DATABASE_POOL_SIZE: "number:min=1:default=10",
  
  // API
  API_URL: "string:url",
  API_KEY: "string:min=32:secret",
  API_TIMEOUT: "number:min=1000:default=5000",
  
  // Authentication
  JWT_SECRET: "string:min=32:secret",
  JWT_EXPIRES_IN: "string:default=7d",
  SESSION_SECRET: "string:min=32:secret",
  
  // Environment
  NODE_ENV: "enum:development,production,test",
  LOG_LEVEL: "enum:debug,info,warn,error:default=info",
  
  // Server
  PORT: "number:min=1:default=3000",
  HOST: "string:default=0.0.0.0",
  CORS_ORIGIN: "string:url",
  
  // Feature Flags
  ENABLE_ANALYTICS: "enum:true,false:default=false",
  ENABLE_CACHE: "enum:true,false:default=true",
});

// All fully typed and validated!

Error Handling in Production

Production Error Handling
import { env, EnvValidationError } from "@liahus/safe-env";

let ENV: ReturnType<typeof env>;

try {
  ENV = env({
    DATABASE_URL: "string:url",
    PORT: "number:default=3000",
    JWT_SECRET: "string:min=32:secret",
  });
} catch (error) {
  if (error instanceof EnvValidationError) {
    // Log error (secrets are already masked)
    console.error("❌ Environment validation failed:");
    console.error(error.message);
    
    // Exit with error code
    process.exit(1);
  }
  throw error;
}

// ENV is guaranteed to be valid here
export { ENV };