Environment variable loading for JavaScript runtimes.
Installation#
npm install @rcompat/envpnpm add @rcompat/envyarn add @rcompat/envbun add @rcompat/envUsage#
Required variables#
Use env.get when a variable must exist. Throws immediately if missing,
so misconfigured environments fail early and explicitly:
import env from "@rcompat/env";
const url = env.get("DATABASE_URL"); // string, throws if missing
const secret = env.get("API_SECRET"); // string, throws if missingOptional variables#
Use env.try when a variable may or may not be present:
import env from "@rcompat/env";
const debug = env.try("DEBUG"); // string | undefined
const nodeEnv = env.try("NODE_ENV"); // string | undefinedAPI Reference#
env.get(key)#
env.get(key: string): string;Returns the value of the environment variable. Throws if the variable is not set.
| Parameter | Type | Description |
|---|---|---|
key |
string |
Environment variable name |
env.try(key)#
env.try(key: string): string | undefined;Returns the value of the environment variable, or undefined if not set.
Never throws.
| Parameter | Type | Description |
|---|---|---|
key |
string |
Environment variable name |
Browsers#
Browser builds expose an empty environment so server environment variables are
not included in client code. Consequently, env.get(key) throws and
env.try(key) returns undefined in browsers.
File loading#
The package looks for the first matching file in your project root:
.env.{NODE_ENV}.local.env.{NODE_ENV}.env.local.env
If NODE_ENV is not set, JS_ENV is used as a fallback. Local files (.local
suffix) are typically gitignored and used for machine-specific secrets.
Merging#
The runtime's native environment is always the base. Node and Bun read from
process.env, while Deno reads from Deno.env. The first .env file found is
layered on top, so file variables win over system variables.
Substitution#
Variables can reference other variables:
FOO=world
BAR=hello$FOO # helloworld
BAZ=hello${FOO} # helloworld
ESCAPED=hello\$FOO # hello$FOO
WITH_DEFAULT=${FOO:-fallback} # uses fallback if FOO is undefinedSubstitution resolves against the merged environment, so system variables are available too:
CONFIG=$HOME/.config/myapp
DB_USERNAME=${DB_USERNAME:-myapp} # uses system DB_USERNAME or falls back to myappDeno permissions#
Deno requires --allow-env to read the system environment and --allow-read
to discover and load dotenv files. Permission failures are reported by Deno
during module initialization rather than being treated as missing variables.
Single-quoted values skip substitution:
FOO='hello$BAR' # hello$BAR (literal)Project structure#
my-project/
├── .env # Shared defaults
├── .env.development # Development settings
├── .env.development.local # Local dev secrets (gitignored)
├── .env.production # Production settings
└── .gitignore.env.local
.env.*.localLicense#
MIT
Contributing#
See CONTRIBUTING.md in the repository root.