@srinath-shrestha/smart-env
v0.1.6
Published
Secure .env loader with schema validation, type safety, defaults, and helpful error reporting
Downloads
12
Maintainers
Readme
smart-env
Secure .env loader with schema validation, type safety, defaults, and helpful error reporting. Minimal runtime overhead. Works out-of-the-box for Node + TypeScript.
Why smart-env?
Traditional .env loaders like dotenv only load environment variables into process.env without any validation, type safety, or defaults. This leads to:
- Runtime errors when required variables are missing
- Type coercion bugs (e.g.,
"false"is truthy) - Secrets leaked via logs or mutable
process.env - Inconsistent defaults across environments
smart-env solves these problems by:
- Validating env vars at boot time with clear error messages
- Providing strong TypeScript types inferred from your schema
- Returning frozen config objects (immutable)
- Supporting defaults in one place
- Optionally scrubbing secrets from
process.env
Installation
npm install @srinath-shrestha/smart-env zod
# or
pnpm add @srinath-shrestha/smart-env zod
# or
yarn add @srinath-shrestha/smart-env zodNote:
zodis a peer dependency. If you prefer not to use Zod, you can use the built-in DSL (see below).
Quick Start
Using Zod (Recommended)
import { loadEnv } from "@srinath-shrestha/smart-env";
import { z } from "zod";
const schema = z.object({
PORT: z.coerce.number().default(3000),
NODE_ENV: z.enum(["development", "production"]).default("development"),
API_KEY: z.string().min(1),
ENABLE_CACHE: z.coerce.boolean().default(false),
});
const env = loadEnv(schema, { strict: true, scrubProcessEnv: true });
// env.PORT is number
// env.API_KEY is string
// env.ENABLE_CACHE is booleanUsing Built-in DSL (No Zod)
import { defineSchema, loadEnv } from "@srinath-shrestha/smart-env";
const schema = defineSchema({
PORT: { type: "number", default: 3000 },
API_KEY: { type: "string", required: true },
ENABLE_CACHE: { type: "boolean", default: false },
});
const env = loadEnv(schema);API
loadEnv(schema, options?)
Loads and validates environment variables.
Options:
strict: boolean- Defaulttrue. Throw on validation errors. Set tofalseto log warnings instead.scrubProcessEnv: boolean- Defaultfalse. Remove loaded keys fromprocess.envafter reading.maskSecrets: boolean- Defaulttrue. Mask secret values in error messages.allowUnknownKeys: boolean- Defaulttrue. Allow extra env vars not in schema.sourceFiles: string[]- Default['.env']. Env files to load.
Returns: Frozen, type-safe config object.
defineSchema(schema)
Define a schema using the built-in DSL (for non-Zod users).
Schema format:
{
KEY_NAME: {
type: "string" | "number" | "boolean",
required?: boolean,
default?: any
}
}Error Messages
When validation fails in strict mode, you get clear, actionable errors:
❌ smart-env: 2 problem(s) found
• API_KEY — missing (required). Add: API_KEY=your_api_key_here
• PORT — invalid type. Expected number, got "abc"Migration from dotenv
Before:
import dotenv from "dotenv";
dotenv.config();
const port = Number(process.env.PORT) || 3000;
const apiKey = process.env.API_KEY; // might be undefinedAfter:
import { loadEnv } from "@srinath-shrestha/smart-env";
import { z } from "zod";
const schema = z.object({
PORT: z.coerce.number().default(3000),
API_KEY: z.string().min(1),
});
const env = loadEnv(schema);
// env.PORT is always a number
// env.API_KEY is guaranteed to existContributing
Contributions welcome!
License
MIT
