Environment
Detect the current runtime environment and auto-load the matching .env files for it.
envapt detects which environment it's running in and loads the matching .env files for it. The isProduction / isStaging / isDevelopment / isTest helpers read that same value.
Detecting the environment
The environment is resolved from the first of these keys that is set, falling back to development:
ENVIRONMENT → ENV → NODE_ENV → MODE → development
MODE is last because Vite-family browser builds expose import.meta.env.MODE but none of the others, so binding new ManualEnvSource(import.meta.env) lets the same helpers work there. See Browser.
Read it as an enum, or through boolean helpers for the common checks.
.environment; // Environment.; // boolean
.;
.;
.;Environment has four members: Development, Staging, Production, and Test. Matching is case-insensitive:
production, staging, test, and development map to their member. Any other value, or no key set at all, falls
back to Development; set Envapter.debug = 'warn' to log that fallback.
Branching on the environment
Use the helpers where behavior should differ per environment.
const logLevel = . ? 'warn' : 'debug';
if (.) {
// wire up dev-only tooling
}Overriding detection
Set Envapter.environment to pin the environment explicitly, regardless of what the env vars say. It accepts the Environment enum or a string.
. = .;
. = 'production'; // strings work tooAn explicit assignment also selects which .env files load on the next read, so set it before reading environment-specific values.
Pin Envapter.environment once, early in your entry file, before any config reads. Setting it after a read means
that read already used the previously detected environment's files.
Per-environment .env files
The cascade reads files from disk, so it runs on Node, Bun, and Deno only. On Cloudflare Workers and in the browser there is no filesystem and no cascade; you bind an environment source instead. See Sources.
For the detected (or overridden) environment (production, staging, development), envapt layers a dotenv-flow cascade, loading the first file that exists at each level, highest precedence first:
.env.${env}.local.env.${env}.env.local.env
So in production it reads .env.production.local → .env.production → .env.local → .env. Values from higher-precedence files win; missing files are skipped.
Precedence is most-specific-wins: .env.production outranks .env.local. This differs from dotenv-flow /
Next.js, where .env.local sits on top. The intent is that a committed .env.production stays authoritative for
that environment even if a stray .env.local is present.
Custom profiles
When your per-environment files live elsewhere, configureProfiles layers explicit paths on top of the cascade for the environments you name. Earlier paths in the array win. configureProfiles and resetProfiles read the filesystem, so they are not available off Node; see Sources.
.({
[.]: { : ['config/prod.env', 'secrets/prod.env'] },
[.]: { : 'config/staging.env' }
});A path you name in configureProfiles must exist. A missing configured path throws EnvaptError with code
EnvFilesNotFound on the next read. The auto-cascade files are skipped when missing, but configured paths are not.
Set useDefaults: false to load only the configured paths and skip the auto-cascade entirely.
.({
[.]: { : 'config/prod.env' },
: false
});
.(); // back to the pure cascadeTo bypass environment-based selection altogether and load a fixed set of files, set Envapter.envPaths directly, covered in Configuration.