Envapter
Read environment variables as typed values with Envapter's static and instance methods, ordered fallbacks, and fail-fast checks.
Envapter is the functional entry point to envapt. Every reader comes two ways: a static method for one-off reads, and an instance method for when you hold a new Envapter() or extend it. Both read from the same parsed cache.
import { } from 'envapt';
// static, for a one-off read
const port = .('PORT', 3000);
// instance, when you hold a reference
const = new ();
const apiUrl = .('API_URL', 'http://localhost');Primitives
Five readers cover the primitive types. Each parses the raw string and returns the matching type.
const = .('APP_NAME', 'envapt'); // string
const = .('PORT', 3000); // number
const = .('DEBUG', false); // boolean
const = .('MAX_UPLOAD_BYTES', 0n); // bigint
const = .('KEY', .('envapt:key')); // symbolgetBoolean reads 1, yes, true, on as true and 0, no, false, off as false, case-insensitively. Anything else uses the fallback.
Fallbacks shape the return type
A fallback supplies the default value and removes undefined from the return type. With a fallback the return is T; without one it's T | undefined, so the type makes you handle the missing case.
const withFallback = .('API_URL', 'http://localhost');
const noFallback = .('API_URL');Ordered keys
Any reader accepts an ordered list of keys instead of a single name. The first key with a present value wins, so an aliased or renamed variable falls back to its old name in one read. An empty value, or a whitespace-only value under strict, is skipped like an unset key.
// READONLY_URL if set, else DATABASE_URL, else the fallback
const db = .(['READONLY_URL', 'DATABASE_URL'], 'sqlite://memory');Pass the array inline. A pre-declared const keys = [...] widens to string[], which does not satisfy the
ordered-key tuple type.
Raw values
getRaw returns the string exactly as loaded, with no type conversion. It exists only as an instance method:
const raw = new ().('DATABASE_URL');Converters
For shapes beyond primitives, two readers take a converter:
getUsing(key, token, fallback?)for built-in converter tokens (arrays, URLs, dates, durations, and more).getWith(key, fn, fallback?)for your own(raw, fallback) => Tfunction.
const origins = .('CORS', .({ : . }));
const retries = .('RETRIES', (, ) => ( ? () : ), 3);Fallbacks behave like the primitives, removing undefined from the return type. The Converters page covers every built-in token.
Template strings
resolve is a tagged template that inlines env values by key, and expands any ${VAR} references inside the resolved values.
// PGUSER=app, PGPASSWORD=secret, PGHOST=db.internal, PGDATABASE=myapp
const dsn = .`postgres://${'PGUSER'}:${'PGPASSWORD'}@${'PGHOST'}/${'PGDATABASE'}`;See Templates for ${VAR} interpolation and cycle protection.
Fail-fast on missing values
require asserts that one or more keys are present and non-empty after template resolution, throwing an EnvaptError that names every missing key. A whitespace-only value counts as missing only under strict mode.
// Assuring all three keys are present at the start of the program, for example
.('DATABASE_URL', 'API_KEY', 'SENTRY_DSN');has returns boolean with the same missing semantics as getRequired. An ordered key list falls through to the first present key. It returns true exactly when a required read of the same key would find a value.
if (!.('SENTRY_DSN')) {
throw new ('Set SENTRY_DSN in your .env before deploying.');
}For a typed fail-fast that returns the parsed value, use getRequired:
const url = .('DATABASE_URL', .);getRequiredAll reads a whole group in one call and returns a typed record, throwing once with every missing key. A spec value is a token, an array() token, or a custom parser, and an optional casing ('camelCase', 'PascalCase', or 'kebab-case') renames the keys. Casing splits on underscores, so it expects the conventional SCREAMING_SNAKE env-var names:
const = .(
{
: .,
: .,
: () => new (.(','))
},
'camelCase'
);
config;They throw on a missing value instead of returning a fallback. See Strict mode for the global switch and how required reads relate to it.
require, getRequired, and getRequiredAll throw EnvaptError for a missing or empty key (or, under strict mode, a whitespace-only one). require and getRequiredAll collect every missing key into one error.
Best to call require and getRequiredAll at startup, not lazily inside a request path, so a missing value fails the boot rather than a live request.
Static vs instance
Statics suit scattered, one-off reads. Create an instance to carry an env reader as a dependency, or extend Envapter to group related config on one class.
class extends {
readonly = this.('PORT', 3000);
readonly = this.('DEBUG', false);
}Static and instance reads hit the same cache.
Environment detection
Envapter also detects the current runtime environment and exposes it through the isProduction / isStaging / isDevelopment / isTest helpers. On Node, Bun, and Deno it auto-loads the matching .env files for that environment. The helpers, the Environment enum, and per-environment file selection are documented on Environment.