@voila.dev/env
Load .env files into process.env or an Effect ConfigProvider: several files, earlier wins, the real environment always wins.
Load .env files without a FileSystem service, the same way in Bun, Node and
tests.
- Several files, earlier wins: list
.env.localbefore.env. - The real environment always wins: an exported CI or production value is never overwritten by a file.
- A missing file is skipped; a malformed line is ignored, not fatal.
bun add @voila.dev/env effectWith Effect
import { environmentFilesLayer } from "@voila.dev/env/effect";
import { Config, Effect } from "effect";
const program = Config.Number("PORT");
Effect.runPromise(
program.pipe(Effect.provide(environmentFilesLayer([".env.local", ".env"]))),
);environmentFilesProvider(paths, options) returns the ConfigProvider itself,
to combine with ConfigProvider.orElse or nested.
Without Effect
For tools that read process.env directly (a drizzle-kit config, a script),
the root entry has no dependency on Effect:
import { loadEnvironmentFiles } from "@voila.dev/env";
loadEnvironmentFiles([".env.local", ".env"]);Also exported: parseEnvironment(text), readEnvironmentFile(path) (null
when missing) and mergeEnvironment(paths, base).
Syntax
KEY=value, export KEY=value, # comments, "double" (with \n and \"
escapes) and 'single' (literal) quotes. An unquoted value ends at #; a
bare # is kept, so pa#ss survives.