Quick Start
Install envapt and read your first typed environment variable.
Install
pnpm add envaptRead a value
Put a variable in your .env:
PORT=8080Read it as a number, with a fallback for when it is unset:
const port = .('PORT', 3000);The fallback supplies the default and removes undefined from the type. See Envapter for the full reader API and Converters for non-primitive types.
Or bind it to a class
The @Envapt decorator binds a value to a typed field. The default form is a TC39 Stage 3 accessor decorator.
class {
@('PORT', { : ., : 3000 })
static accessor : number;
}Static fields use static accessor x: T, instance fields use accessor x!: T. If your project already runs on
experimentalDecorators, import the legacy form from envapt/legacy instead. See
Decorators.
Mirror loaded values to process.env
Import envapt/config to load the .env cascade and mirror every loaded key into process.env in one step, so process.env.PORT works without touching Envapter. This is the same pattern as the dotenv/config import, so code that reads process.env directly still sees the values.
import 'envapt/config';
const = ..; // the loaded keys are now on process.envIt is the side-effect form of Envapter.syncProcessEnv = true plus an eager load, and follows the same collision rules. Unlike dotenv/config, it loads the whole per-environment cascade, not a single .env.
Preload it without editing your entry file:
node --import envapt/config app.js # ESM
node -r envapt/config app.js # CommonJSFor typed reads on top, keep using Envapter.
Requirements
envapt runs on Node >=20, Bun >=1.3, Deno >=2.5, Cloudflare Workers, and the browser. On Node, Bun, and Deno a source binds on import, on Workers and in the browser you bind one yourself. The functional API needs no build step on any runtime. The default decorator API uses TC39 accessor decorators, which run on Bun and Deno executing a .ts file directly. The legacy decorators (envapt/legacy) need compilation with experimentalDecorators. See Compatibility.