npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ironfighter23/env-guard

v1.1.2

Published

Zero-dependency environment variable validator with type coercion, full TypeScript inference, ESM + CJS support, and beautiful dev-time error reporting.

Readme

env-guard

Zero-dependency environment variable validator for Node.js.
Define a schema once — get type coercion, validation, and beautiful error output at startup.

CI npm version License: MIT


The problem

Every Node.js app reads from process.env. But process.env gives you raw strings — no types, no validation, no defaults. This leads to:

  • Silent failures when PORT is undefined (or the string "undefined")
  • Type bugs: ENABLE_CACHE === "false" is truthy in JS
  • Missing variables discovered at runtime, not startup
  • No documentation of what variables your app actually needs
  • No .env.example to onboard new developers

Most teams write the same boilerplate fix over and over. env-guard solves it once.


Features

  • Zero dependencies — pure Node.js, works in any environment
  • Type coercion — strings become numbers, booleans, parsed JSON, validated URLs
  • Schema-first — define variables once, get docs for free
  • All errors at once — see every missing/invalid variable in a single error, not one at a time
  • Beautiful error output — colour-coded, with hints and examples right in the terminal
  • .env.example generator — auto-generate from your schema
  • Built-in .env loader — no dotenv needed
  • Fluent API — chain .min(), .max(), .matches(), .default(), .sensitive(), .deprecated()
  • CLI toolnpx env-guard --check validates before deploy

Install

npm install @ironfighter23/env-guard

Quick start

// config.js — run this at the very top of your app
const { guard, schema } = require('@ironfighter23/env-guard');

const config = guard({
  PORT:         schema.port().default(3000),
  DATABASE_URL: schema.url().sensitive(),
  NODE_ENV:     schema.enum(['development', 'staging', 'production']),
  SECRET_KEY:   schema.string().min(32).sensitive(),
  ENABLE_CACHE: schema.boolean().default(false),
});

// config is now frozen, type-safe, and fully validated:
// config.PORT         → 3000   (number)
// config.ENABLE_CACHE → false  (boolean)
// config.DATABASE_URL → "postgresql://..."

module.exports = config;

If any variable is missing or invalid, env-guard fails fast with a clear error before your app starts:

╔═ env-guard: invalid environment ══════════════════╗

  ✖  DATABASE_URL
     "DATABASE_URL" is required but was not set
     hint: PostgreSQL connection string
     example: DATABASE_URL=postgresql://user:pass@localhost:5432/db

  ✖  SECRET_KEY
     SECRET_KEY length must be >= 32 (got 10)

╚══════════════════════════════════════════════════╝

  Run "npx env-guard --check" to validate your .env file

API Reference

guard(schema, options?)

Validates process.env (or a custom env object) against a schema. Returns a frozen config object with coerced values. Throws EnvGuardError if validation fails.

const config = guard(schemaMap, {
  env:    process.env,  // custom env source (default: process.env)
  bail:   false,        // stop at first error (default: false = collect all)
  quiet:  false,        // suppress success log (default: false)
  strict: false,        // fail on undeclared variables (default: false)
});

Schema types

| Method | Input | Output | Notes | |--------|-------|--------|-------| | schema.string() | any string | string | | | schema.number() | "3.14" | 3.14 | float | | schema.integer() | "42" | 42 | rejects floats | | schema.boolean() | "true"/"1"/"yes"/"on" | true | case-insensitive | | schema.port() | "3000" | 3000 | 1–65535 | | schema.url() | "https://..." | "https://..." | uses URL constructor | | schema.email() | "[email protected]" | "[email protected]" | basic format check | | schema.host() | "localhost" | "localhost" | hostname or IP | | schema.json() | '{"a":1}' | { a: 1 } | parsed JSON | | schema.enum([...]) | "dev" | "dev" | must be in list |


Field modifiers

Chain these onto any schema type:

schema.string()
  .optional()              // not required
  .default('hello')        // default value (implies optional)
  .describe('A description shown in .env.example and error hints')
  .example('my-value')     // shown in .env.example
  .sensitive()             // value redacted in any output
  .deprecated('Use NEW_VAR instead')  // warns if the variable is set
  .validate((value, name) => {
    // throw an Error to fail validation
    if (!value.startsWith('sk-')) throw new Error(`${name} must start with "sk-"`);
  })
  .min(5)                  // min value (number) or min length (string)
  .max(100)                // max value (number) or max length (string)
  .matches(/^v\d+$/)       // must match regex

loadEnv(path?, options?)

Parse and load a .env file into process.env. No dotenv needed.

const { loadEnv } = require('@ironfighter23/env-guard');

loadEnv('.env');                           // load .env
loadEnv('.env.local', { override: true }); // override existing vars
loadEnv('.env', { silent: true });         // don't throw if missing

Supports:

  • KEY=value
  • KEY="value with spaces"
  • KEY='single quoted'
  • export KEY=value
  • Inline comments: KEY=value # this is ignored
  • \n escape in double-quoted strings

generateExample(schemaMap)

Generate .env.example content from a schema:

const { generateExample } = require('@ironfighter23/env-guard');
const schemaMap = require('./env.schema.js');

const content = generateExample(schemaMap);
console.log(content);
// # .env.example — generated by env-guard
// # PORT
// # HTTP server port | required
// PORT=8080
// ...

parseEnvFile(content)

Parse a .env file string into a plain object (does NOT write to process.env):

const { parseEnvFile } = require('@ironfighter23/env-guard');
const parsed = parseEnvFile(fs.readFileSync('.env', 'utf8'));
// { PORT: '3000', NODE_ENV: 'development', ... }

CLI

# Validate your .env against a schema
npx env-guard --check

# Custom paths
npx env-guard --check --env .env.local --schema config/env.schema.js

# Generate a .env.example from your schema
npx env-guard --generate

# Print .env.example to stdout
npx env-guard --example

# List all validators and modifiers
npx env-guard --docs

Schema file for CLI

Create env.schema.js in your project root:

const { schema } = require('@ironfighter23/env-guard');

module.exports = {
  PORT:         schema.port().default(3000).describe('HTTP server port'),
  DATABASE_URL: schema.url().describe('Postgres connection string').sensitive(),
  NODE_ENV:     schema.enum(['development', 'staging', 'production']),
  SECRET_KEY:   schema.string().sensitive().min(32),
};

Framework recipes

Express.js

// server.js
require('@ironfighter23/env-guard').loadEnv();  // load .env first

const { guard, schema } = require('@ironfighter23/env-guard');
const express = require('express');

const config = guard({
  PORT: schema.port().default(3000),
  NODE_ENV: schema.enum(['development', 'production']).default('development'),
  DATABASE_URL: schema.url().sensitive(),
});

const app = express();
app.listen(config.PORT, () => {
  console.log(`Server running on port ${config.PORT}`);
});

Next.js

// lib/config.js
const { guard, schema } = require('@ironfighter23/env-guard');

module.exports = guard({
  // Server-side only
  DATABASE_URL: schema.url().sensitive(),
  JWT_SECRET:   schema.string().min(32).sensitive(),

  // Exposed to client (NEXT_PUBLIC_ prefix)
  NEXT_PUBLIC_API_URL:   schema.url().describe('Public API base URL'),
  NEXT_PUBLIC_APP_NAME:  schema.string().default('My App'),
});

With TypeScript

import { guard, schema } from '@ironfighter23/env-guard';

const config = guard({
  PORT:         schema.port().default(3000),
  DATABASE_URL: schema.url(),
  NODE_ENV:     schema.enum(['development', 'production'] as const),
  ENABLE_CACHE: schema.boolean().default(false),
});

// Full automatic inference — zero casting needed:
// config.PORT         → number
// config.NODE_ENV     → 'development' | 'production'
// config.ENABLE_CACHE → boolean

Integration with CI/CD

Add a pre-deploy validation step:

# .github/workflows/deploy.yml
- name: Validate environment
  run: npx env-guard --check --env .env.production --strict
  env:
    DATABASE_URL: ${{ secrets.DATABASE_URL }}
    SECRET_KEY:   ${{ secrets.SECRET_KEY }}
    NODE_ENV:     production

Comparison

| Feature | env-guard | dotenv | envalid | zod (manual) | |---------|-----------|--------|---------|-------------| | Zero dependencies | ✅ | ✅ | ❌ | ❌ | | Type coercion | ✅ | ❌ | ✅ | ✅ | | Collect all errors | ✅ | ❌ | ✅ | ✅ | | .env loader built-in | ✅ | ✅ | ❌ | ❌ | | .env.example generator | ✅ | ❌ | ❌ | ❌ | | CLI validator | ✅ | ❌ | ❌ | ❌ | | Fluent builder API | ✅ | ❌ | partial | ❌ | | Frozen result | ✅ | ❌ | ❌ | ❌ | | Deprecated warnings | ✅ | ❌ | ❌ | ❌ |


Contributing

Pull requests are welcome. Please:

  1. Fork the repo and create a feature branch
  2. Add tests for any new feature (test/index.test.js)
  3. Run npm test — all tests must pass
  4. Open a PR with a clear description

License

MIT © Nishant Bhatte