env is a dependency-free TypeScript and JavaScript library for loading .env files and reading process.env with typed helpers.
Key features:
.env values into process.env.npm install @sourceregistry/node-env
npx jsr add @sourceregistry/node-env
import { env } from "@sourceregistry/node-env";
const appName = env.string("APP_NAME", "MyApp");
const sameSite = env.enum("PUBLIC_SESSION_SAME_SITE", ["strict", "lax", "none"] as const, "lax");
const port = env.number("PORT", 3000);
const debug = env.boolean("DEBUG", false);
If a key is missing or invalid, the accessor falls back to the provided default and normalizes process.env to that value.
const port = env.number("PORT", 3000);
const cache = env.boolean("ENABLE_CACHE", false);
Boolean parsing accepts "true", "1", "yes", and "on" as true, and "false", "0", "no", and "off" as false.
process.env.FLAG = "yes";
console.log(env.boolean("FLAG", false)); // true
const api = env.collection("API_");
const config = env.collection("API_", {
removePrefix: true,
reviver: (value, key) => key === "TIMEOUT" ? Number(value) : value
});
Use env.schema when application startup should fail fast on invalid configuration.
import { env, SchemaValidationError } from "@sourceregistry/node-env";
const envSchema = env.schema.object({
NODE_ENV: env.schema.enum(["development", "test", "production"] as const),
PORT: env.schema.number({ integer: true, min: 1, default: 3000 }),
DATABASE_URL: env.schema.url({ protocols: ["https:"] }),
ENABLE_CACHE: env.schema.boolean({ default: false }),
ALLOWED_HOSTS: env.schema.csv(),
});
try {
const config = env.schema.parse(envSchema);
config.PORT; // number
config.DATABASE_URL; // URL
config.ENABLE_CACHE; // boolean
config.ALLOWED_HOSTS; // string[] | undefined
} catch (error) {
if (error instanceof SchemaValidationError) {
console.error(error.errors);
}
throw error;
}
Schema object keys must be uppercase:
env.schema.object({
PORT: env.schema.number(),
DATABASE_URL: env.schema.url(),
});
Use env.schema.safeParse() if you want a result object instead of an exception.
Use env.config.map() when you want to define the final app config structure directly:
const runtimeConfig = env.config.map({
nodeEnv: env.config.field(
"NODE_ENV",
env.schema.enum(["development", "test", "production"] as const, {
default: "development",
})
),
serverPort: env.config.field(
"PUBLIC_SERVER_PORT",
env.schema.number({ integer: true, min: 1, max: 65_535, default: 3000 })
),
allowedHosts: env.config.field(
"PUBLIC_ALLOWED_HOSTS",
env.schema.csv()
),
});
env.config.safeMap() returns { success, data | errors } instead of throwing.
The package ships with a built-in dependency-free validator, but the root export also exposes adaptSchema() so you can wrap another runtime schema library later without coupling your app to an internal helper module.
import { adaptSchema, env, validation } from "@sourceregistry/node-env";
const externalSchema = {
safeParse(value: unknown) {
return typeof value === "string"
? { success: true as const, data: value }
: { success: false as const, issues: [{ message: "Expected string" }] };
},
};
const ExternalString = adaptSchema<typeof externalSchema, string>(externalSchema, {
safeParse(schema, value) {
return schema.safeParse(value);
},
});
validation.parse(ExternalString, "ok");
env.config.field("APP_NAME", ExternalString);
Use env.schema.csv() for comma-separated env variables:
const envSchema = env.schema.object({
PUBLIC_ALLOWED_HOSTS: env.schema.csv(),
PUBLIC_TRUSTED_PROXIES: env.schema.csv({
default: ["127.0.0.1"],
}),
});
| Method | Description |
|---|---|
env.string(key, default?) |
Return the variable as a string or the fallback. |
env.enum(key, values, default?) |
Return a string enum value or the fallback. |
env.number(key, default?) |
Return the variable as a number or the fallback. |
env.boolean(key, default?) |
Return the variable as a boolean or the fallback. |
env.url(key, default?) |
Return the variable as a URL or the fallback. |
env.has(key) |
Return true if the env key exists. |
env.defined(key) |
Return true if the env key exists and is not undefined. |
env.assert(keys, errorBuilder?) |
Throw if one or more required keys are missing. |
env.collection(prefix, options?) |
Return an object of env values that share a prefix. |
env.utils.select(key, TRUE, FALSE, predicate?) |
Select between two values based on an env predicate. |
env.dev |
Return true unless NODE_ENV === "production". |
env.schema |
Build and parse typed env schemas from process.env. |
env.config |
Map validated env fields directly into your final app config object. |
npm test
npm run test:coverage
npm run verify
npm run jsr:check
PRs are welcome. Please:
Found a security issue? Report it responsibly.
GitHub: github.com/SourceRegistry/node-env
npm: @sourceregistry/node-env
JSR: @sourceregistry/node-env