ConfigProvider
Data sources used by Config to load raw configuration values. A ConfigProvider reads paths from places such as environment variables, JavaScript objects, .env contents, or directories, and returns a uniform Node shape that config schemas can decode. The module also includes helpers for composing providers, changing paths, and installing providers through layers.
Combinators
constantCase
Signature
declare const constantCase: (self: ConfigProvider) => ConfigProvider;Transforms the path segments before they reach the underlying store.
When to use
Use when you need to rename, re-case, or otherwise transform config path segments before lookup.
Details
The function f receives the whole path produced by earlier provider transformations and must return a new path. Lookup path transformations compose in application order: the existing transformation runs first, then f runs. For providers composed with orElse, the transformation is applied to each operand.
The combinator delegates transformation to the provider itself. Use make for custom sources so this capability is implemented automatically.
See
constantCase– a preset that converts toCONSTANT_CASEnested– for prepending a prefix instead of transforming
Signature
declare const mapInput: {
(f: (path: Path) => Path): (self: ConfigProvider) => ConfigProvider;
(self: ConfigProvider, f: (path: Path) => Path): ConfigProvider;
};Scopes a provider so that all lookups are prefixed with the given path segments.
When to use
Use to namespace config under a prefix like "app" or "database", or reuse the same provider shape for multiple sub-configs.
Details
Accepts a single string or a full Path array. For providers composed with orElse, the prefix is applied to each operand. Supports both data-last and data-first calling conventions.
Gotchas
Ordering matters when composing with mapInput or constantCase. Later provider transformations run after earlier ones: a later nested becomes the outer prefix, and a later mapInput sees the whole path produced by previous transformations.
See
mapInput– for arbitrary path transformations
Signature
declare const nested: {
(prefix: string | Path): (self: ConfigProvider) => ConfigProvider;
(self: ConfigProvider, prefix: string | Path): ConfigProvider;
};Returns a provider that falls back to that when self returns undefined for a path.
When to use
Use to layer multiple config sources, such as env vars plus a defaults file, or provide partial overrides on top of a base config.
Details
Each provider keeps its own path transformations. If the combined provider is later transformed with mapInput or nested, the transformation is applied to both sides.
Gotchas
The fallback only runs when the path is not found (undefined). A SourceError from self is not caught; it propagates immediately.
See
layerAdd– install a fallback provider via a Layer
Signature
declare const orElse: {
(that: ConfigProvider): (self: ConfigProvider) => ConfigProvider;
(self: ConfigProvider, that: ConfigProvider): ConfigProvider;
};Constructors
Creates a ConfigProvider that reads configuration from a directory tree on disk, where each file is a leaf value and each directory is a container.
When to use
Use when you expose each config key as a file under a directory, such as Kubernetes ConfigMap or Secret volume mounts.
Details
Resolution tries a regular file first and returns a Value node for non-empty trimmed file contents. If the file read fails, it tries a directory and returns a Record node with immediate child names as keys. If both fail with NotFound, it returns undefined. Other platform failures return SourceError.
Requires Path and FileSystem in the Effect context. Defaults to root path /; override with { rootPath: "/etc/config" }.
Literal empty strings are treated as missing values by default after file contents are trimmed. Pass { preserveEmptyStrings: true } to keep empty strings as explicit values. Directory listings still reflect the file names present on disk.
See
fromEnv– for environment variablesfromDotEnv– for.envfiles
Signature
declare const fromDir: (options?: {
readonly preserveEmptyStrings?: boolean;
readonly rootPath?: string;
}) => Effect.Effect<ConfigProvider, never, Path_.Path | FileSystem.FileSystem>;fromDotEnv
Creates a ConfigProvider by reading and parsing a .env file from the file system.
When to use
Use to load environment config from a .env file at application startup.
Details
Requires FileSystem in the Effect context. Defaults to reading ".env" in the current directory; override with { path: "/custom/.env" }. Variable expansion (for example, ${VAR}) is disabled by default; enable with { expandVariables: true }.
Literal empty strings are treated as missing values when loaded as values by default. Pass { preserveEmptyStrings: true } to keep empty strings as explicit values. Child discovery still reflects the keys present in the parsed .env source.
Returns an Effect that resolves to a ConfigProvider. Fails with a PlatformError if the file cannot be read.
See
fromDotEnvContents– parse a.envstring directlyfromEnv– read from the runtime environment
Signature
declare const fromDotEnv: (options?: {
readonly expandVariables?: boolean;
readonly path?: string;
readonly preserveEmptyStrings?: boolean;
}) => Effect.Effect<ConfigProvider, PlatformError, FileSystem.FileSystem>;fromDotEnvContents
Creates a ConfigProvider by parsing the string contents of a .env file.
When to use
Use when you already have the .env contents as a string, such as contents fetched from a remote store or embedded in a test.
Details
Supports export prefixes, single/double/backtick quoting, inline comments, and escaped newlines. Variable expansion (for example, ${VAR}) is disabled by default; enable with { expandVariables: true }.
Literal empty strings are treated as missing values when loaded as values by default. Pass { preserveEmptyStrings: true } to keep empty strings as explicit values. Child discovery still reflects the keys present in the parsed .env source.
Parsing is based on the dotenv / dotenv-expand algorithm.
Internally delegates to fromEnv with the parsed key-value pairs.
See
fromDotEnv– loads a.envfile from diskfromEnv– for raw environment variable access
Signature
declare function fromDotEnvContents(
lines: string,
options?: {
readonly expandVariables?: boolean;
readonly preserveEmptyStrings?: boolean;
},
): ConfigProvider;Creates a ConfigProvider backed by environment variables.
When to use
Use to read configuration from process.env, which is the default when no provider is explicitly set, or pass a custom env record for testing or non-Node runtimes.
Details
Path segments are joined with _ for direct lookup, and env var names are also split on _ to build a trie for child key discovery. This means DATABASE_HOST=localhost is accessible at both path ["DATABASE_HOST"] and ["DATABASE", "HOST"]. If all immediate children of a trie node have purely numeric names, the node is reported as an Array; otherwise as a Record.
The default environment merges process.env and import.meta.env (when available). Override by passing { env: { ... } }.
Literal empty strings are treated as missing values when loaded as values by default. Pass { preserveEmptyStrings: true } to keep empty strings as explicit values. Child discovery still reflects the environment variable names present in the source.
Never fails with SourceError — all lookups are synchronous.
See
fromUnknown– for JSON objectsconstantCase– bridge camelCase keys to SCREAMING_SNAKE_CASE
Signature
declare function fromEnv(options?: {
readonly env?: Record<string, string>;
readonly preserveEmptyStrings?: boolean;
}): ConfigProvider;fromUnknown
Creates a ConfigProvider backed by an in-memory JavaScript value (typically a parsed JSON object).
When to use
Use when you need deterministic config from an in-memory JavaScript value, such as in tests, embedded config, or parsed JSON.
Details
Path traversal follows standard JS rules: string segments index into object keys, numeric segments index into arrays. Returns undefined for any path that cannot be resolved. Never fails with SourceError.
Primitive values (number, boolean, bigint) are stringified via String(...).
Literal empty strings are treated as missing values when loaded as values by default. Pass { preserveEmptyStrings: true } to keep empty strings as explicit values.
Gotchas
Object keys and array lengths reflect the original input shape. A leaf value of "" is treated as missing when that leaf is loaded, but the parent container still reports its original keys or length.
See
Signature
declare function fromUnknown(
root: unknown,
options?: {
readonly preserveEmptyStrings?: boolean;
},
): ConfigProvider;Creates a ConfigProvider from a raw lookup function.
When to use
Use when implementing a provider backed by a custom store, such as a database, remote API, or in-memory map.
Details
The get callback receives a Path and must return Effect<Node | undefined, SourceError>. Return undefined when the path does not exist, a Node when it does, and fail with SourceError only when the source cannot be read.
Providers created by make also implement the path-transformation capability used by mapInput, constantCase, and nested.
See
fromEnv– pre-built provider for environment variablesfromUnknown– pre-built provider for JSON objects
Signature
declare function make(get: (path: Path) => Effect<Node | undefined, SourceError>): ConfigProvider;Creates an Array node representing an indexed container with a known length.
When to use
Use when you need to describe a JSON array or numerically indexed env vars inside a custom provider.
Details
The optional value allows a node to be both a container and a leaf at the same time.
See
makeValue– for terminal leavesmakeRecord– for object-like containers
Signature
declare function makeArray(length: number, value?: string): Node;makeRecord
Creates a Record node representing an object-like container with known child keys.
When to use
Use when you need to describe a directory or JSON object inside a custom provider.
Details
The optional value allows a node to be both a container and a leaf at the same time (for example, an env var A=x that also has children A_FOO and A_BAR).
See
Signature
declare function makeRecord(keys: ReadonlySet<string>, value?: string): Node;Creates a Value node representing a terminal string leaf.
When to use
Use when building nodes inside a custom ConfigProvider's get callback.
Details
The function returns a new plain object.
See
makeRecord– for object-like containersmakeArray– for array-like containers
Signature
declare function makeValue(value: string): Node;Errors
SourceError
Typed error indicating that a configuration source could not be read.
When to use
Use when you need to report that a custom provider's underlying store is unreachable or produced an I/O error while reading configuration data.
Gotchas
Do not use SourceError for "key not found". That case is represented by returning undefined from load.
See
ConfigProvider– the interface whoseloadmay fail with this error
Signature
declare class SourceError extends YieldableError<this> & {
readonly _tag: "SourceError";
} & Readonly<{
readonly cause?: unknown;
readonly message: string;
}> {
constructor(args: {
readonly cause?: unknown;
readonly message: string;
});
}Layers
Provides a layer that installs a ConfigProvider as the active provider for all downstream effects, replacing any previously installed provider.
When to use
Use to set the config source for an entire application or test suite.
Details
Accepts either a plain ConfigProvider or an Effect that produces one. When given an Effect, it is evaluated once when the layer is built.
See
layerAdd– add a provider without replacing the existing one
Signature
declare function layer<E = never, R = never>(
self: ConfigProvider | Effect<ConfigProvider, E, R>,
): Layer<never, E, Exclude<R, Scope>>;Creates a Layer that composes a new ConfigProvider with the currently active one, rather than replacing it.
When to use
Use to add defaults that should only apply when the primary provider has no value for a path, or override specific keys while keeping the rest from the existing provider by setting asPrimary: true.
Details
By default, the new provider acts as a fallback and is consulted only when the current provider returns undefined. Set asPrimary: true to make the new provider the primary source, with the existing one as fallback.
See
Signature
declare function layerAdd<E = never, R = never>(
self: ConfigProvider | Effect<ConfigProvider, E, R>,
options?: {
readonly asPrimary?: boolean;
},
): Layer<never, E, Exclude<R, Scope>>;Models
A discriminated union describing the shape of a configuration value at a given path.
When to use
Use when implementing a custom ConfigProvider by returning raw nodes from the get callback passed to make, or when inspecting raw provider output before schema parsing.
Details
Value is a terminal string leaf. Record is an object-like container whose immediate child keys are known and may carry an optional co-located value. Array is an indexed container with a known length and may also carry an optional co-located value.
Provider lookups return undefined when no node exists at the requested path. Within a node that was found, value: undefined has a narrower structural meaning: the container exists but has no co-located scalar value.
See
makeValue– construct aValuenodemakeRecord– construct aRecordnodemakeArray– construct anArraynode
Signature
type Node =
| {
readonly _tag: "Value";
readonly value: string;
}
| {
readonly _tag: "Record";
readonly keys: ReadonlySet<string>;
readonly value: string | undefined;
}
| {
readonly _tag: "Array";
readonly length: number;
readonly value: string | undefined;
};An ordered sequence of string or numeric segments that addresses a node in the configuration tree. String segments name object keys; numeric segments index into arrays.
When to use
Use to address raw configuration nodes when implementing or transforming a ConfigProvider.
Signature
type Path = ReadonlyArray<string | number>;Services
ConfigProvider
Context reference for the active raw configuration provider, registered in the context with a default value of fromEnv(). Because it is a Context.Reference, it is available without explicit provision; Config schemas automatically resolve it.
When to use
Use to override the active raw configuration provider for an entire program, or retrieve the current provider inside an Effect.
See
Signature
declare const ConfigProvider: Reference<ConfigProvider>;ConfigProvider interface
The core interface for loading raw configuration data.
When to use
Use to type-annotate variables that hold a provider or to implement a custom provider via make.
Details
load(path) is the semantic lookup operation used by the Config module. It applies provider transformations and composition before consulting the underlying source. undefined means "not found", a Node means the path exists, and SourceError means the source itself failed.
mapInput(f) is the provider's path-transformation capability. Keeping this capability on the provider allows source and composite providers to preserve their own lookup behavior without exposing an internal representation. Transformations compose in application order: f receives the path produced by earlier transformations.
load deliberately accepts only a Path. Path transformation is modeled by returning another provider through mapInput, rather than by adding a transformation callback to every lookup. Custom implementations therefore expose lookup and transformation behavior, but no source or composition state.
See
Signature
interface ConfigProvider extends Pipeable {
readonly load: (path: Path) => Effect<Node | undefined, SourceError>;
readonly mapInput: (f: (path: Path) => Path) => ConfigProvider;
}
Converts all string path segments to
CONSTANT_CASEbefore lookup.When to use
Use to bridge camelCase schema keys to
SCREAMING_SNAKE_CASEenvironment variables.Details
Numeric segments are left unchanged. String segments use
String.configCaseso numeric word groups such asv2are preserved for environment variable names. This is a specialization of mapInput.See
mapInput– for arbitrary path transformations