Package Exports
- envapt
- envapt/config
- envapt/legacy
- envapt/package.json
Readme
envapt
The apt way to read typed config.
Read config from any source as real typed values, with zero runtime dependencies.
envapt returns config as the type you asked for instead of the string | undefined you get raw, with
a fallback that removes undefined from the return type. It reads from whatever source you bind. On
Node, Bun, and Deno that is process.env and your .env files, bound on import. On Cloudflare
Workers, in the browser, or for a secrets object you fetched at boot, you bind the source with
Envapter.useSource(...).
import { Envapter } from 'envapt';
const port = Envapter.getNumber('PORT', 3000); // number, not string | undefinedWhat you get
- Typed values. A fallback removes
undefinedfrom the return type. Built-in converters cover numbers, booleans, bigint, JSON, URLs, regular expressions, dates, durations, and arrays, or pass your own function or a Standard Schema validator (zod, valibot, arktype). - Any source. A source is any object with a
readVars()method, so you can bindprocess.env, a Cloudflare Workers binding, a browser bundle, or a secrets payload you fetched from a store at boot. On Node, Bun, and Deno one binds on import. - Zero runtime dependencies. The reader, converters, and built-in
.envparser are self-contained, so nothing is added to your dependency tree. - Runs on Node, Bun, Deno, Cloudflare Workers, and the browser. Node
>=20, Bun>=1.3, Deno>=2.5(ESM and CJS). The portable build resolves through the packageexportsconditions. .envloading built in on Node. The default Node source adds a per-environment file cascade,${VAR}templates, and strict / required checks. Off Node there is no filesystem, so you bind another source withEnvapter.useSource(...)and read with the same typed API.
Install
npm install envapt
pnpm add envapt
yarn add envapt
bun add envapt
deno add jsr:@materwelon/envaptQuick start
Read values functionally with Envapter, or bind them to class fields with the @Envapt decorator.
Both share the same parsing, converters, and cache.
Functional
Read a value from any call site, in JavaScript or TypeScript. No build step. On Node the source is
bound for you. On Workers and in the browser, call Envapter.useSource(...) first.
import { Envapter, Converters } from 'envapt';
const port = Envapter.getNumber('PORT', 3000);
const origins = Envapter.getUsing('ALLOWED_ORIGINS', Converters.array(), []);On Cloudflare Workers, env is importable at module scope, so bind it once in a config module, and in
the browser seed a PortableSource from the object your bundler injects.
import { env } from 'cloudflare:workers';
import { Envapter, PortableSource } from 'envapt';
Envapter.useSource(new PortableSource(env));
export const apiToken = Envapter.get('API_TOKEN');Decorator
Bind a value to a class field with a TC39 accessor decorator. No experimentalDecorators flag, and it runs on Bun and Deno from .ts directly.
import { EnvNum } from 'envapt';
class Config {
@EnvNum('PORT', 3000)
static accessor port: number;
}The legacy (experimentalDecorators) decorators are exported from envapt/legacy.
Agent skill
Install the envapt agent skill so AI coding tools use the correct API:
npx skills add materwelonDhruv/envaptBuilt by @materwelonDhruv · Apache 2.0