smart-env-check
v0.1.0
Published
Validate and type-check environment variables at Node.js startup
Downloads
42
Maintainers
Readme
smart-env-check
Validate and type-check Node.js environment variables at startup — zero runtime dependencies, TypeScript-first.
Install
npm install smart-env-checkQuickstart
Load .env in your app (this package does not load dotenv for you), define a schema, and export the validated result:
import "dotenv/config";
import { validateEnv } from "smart-env-check";
export const env = validateEnv({
DATABASE_URL: "string",
PORT: { type: "number", default: 3000 },
DEBUG: { type: "boolean", default: false },
LOG_LEVEL: { type: "string", optional: true },
});env is a frozen object with coerced types. Import it anywhere instead of reading process.env directly.
API
Schema shorthand
Required fields use a type string:
validateEnv({
DATABASE_URL: "string",
PORT: "number",
DEBUG: "boolean",
});Optional and defaults
Use the object form when a variable is optional or has a default:
validateEnv({
PORT: { type: "number", default: 3000 },
LOG_LEVEL: { type: "string", optional: true },
});optional: true(no default) →string | undefinedwhen absentdefault→ used when the variable is missing or empty; do not combine withoptional: true
options.env
By default, validateEnv reads process.env. Pass a custom source for tests or explicit injection:
const env = validateEnv({ PORT: "number" }, { env: { PORT: "3000" } });Only keys in the schema are read; extra keys are ignored.
Supported types
| Type | Coercion rules |
| --------- | ----------------------------------------------------------------------- |
| string | Trim whitespace; returns the trimmed string |
| number | Trim, then Number(); rejects NaN and non-numeric strings |
| boolean | Trim, then case-insensitive: true/1 → true, false/0 → false |
Empty values: "" and whitespace-only strings are treated as absent (missing), not as valid values.
Errors
Validation failures throw EnvValidationError with an issues array:
import { EnvValidationError, validateEnv } from "smart-env-check";
try {
validateEnv({ PORT: "number" }, { env: { PORT: "not-a-number" } });
} catch (error) {
if (error instanceof EnvValidationError) {
console.log(error.issues);
// [{ key: "PORT", code: "invalid_type", message: "..." }]
}
}All schema errors are collected before throwing — no partial results.
Safe logging
Validation errors never include secret env values in message or received for sensitive keys (e.g. SECRET, PASSWORD, TOKEN, API_KEY, DATABASE_URL) or for any string field.
In production, log keys and codes only — not full error messages that might echo user input:
catch (error) {
if (error instanceof EnvValidationError) {
logger.error("Env validation failed", {
issues: error.issues.map(({ key, code }) => ({ key, code })),
});
}
}TypeScript
Return types are inferred from your schema — no manual generics:
const env = validateEnv({
PORT: "number",
LOG_LEVEL: { type: "string", optional: true },
});
env.PORT; // number
env.LOG_LEVEL; // string | undefinedTesting
Inject env values instead of mutating process.env:
import { validateEnv } from "smart-env-check";
const env = validateEnv(
{ API_KEY: "string", PORT: "number" },
{ env: { API_KEY: "test-key", PORT: "3000" } },
);Requirements
- Node.js >= 20
License
MIT
Contributing
See the docs/ folder for product, API, architecture, and security specifications.
