Documentation
¶
Overview ¶
Package config loads layered JSON configuration and defines the contract a configuration type implements to take part in that load.
The contract ¶
A configuration is a type T whose pointer implements Config: a Merge that overlays another instance's set fields onto the receiver, and a Finalize that composes its environment override names from a prefix, applies defaults, reads the overrides, and validates. The methods stay concretely typed against T — an implementation writes Merge(*T) and Finalize(envPrefix string) error against its own type, with no type assertions.
Layered load ¶
Load reads up to four files from a directory, in a fixed precedence, and merges each one that exists onto a zero value of T:
- a base file (config.json),
- an environment overlay (config.<env>.json),
- a secrets file (secrets.json), and
- a secrets overlay (secrets.<env>.json).
The active environment is the value of the Options.EnvVar variable — named explicitly, or derived from Options.EnvPrefix as the prefixed "env" name; when it resolves empty, both overlays are skipped. A single Options.OverlayPattern produces both overlay names from the base and secrets stems; Load validates the pattern and fails a malformed one rather than silently skipping the overlays it names. Every file is optional: a missing file is skipped, so a load with no files present yields a configuration carrying only what Finalize supplies. Any other read error, or malformed JSON, stops the load.
Later sources win: the secrets overlay overrides the secrets file, which overrides the environment overlay, which overrides the base. A set source field always wins over an unset receiver. Finalize runs once, after every file has been merged, receiving Options.EnvPrefix.
Environment overrides ¶
A capability pairs its configuration with an Env struct naming the variables its Finalize reads. Env fields are excluded from JSON and are output, not input: each Finalize composes its own names from the prefix it receives and records them on Env for introspection. An empty prefix composes no names, so nothing in the environment applies — the hermetic form tests rely on — and once a prefix is supplied, the overrides Finalize reads take precedence over every file.
EnvName composes an environment-variable name from a prefix and parts. Each segment upper-cases, and runs of characters outside A-Z and 0-9 collapse to single underscores ("db host" becomes DB_HOST), so a caller can vary the prefix without the capability hard-coding one.
Durations ¶
Duration is a time.Duration that takes part in JSON configuration. It unmarshals from the string form time.ParseDuration accepts ("1m30s") or from a bare integer number of nanoseconds; a fractional number is rejected — the string form expresses sub-second durations — and JSON null leaves the value unchanged. It marshals as the string form, and Duration.Duration returns the value as a time.Duration where an API wants the standard type.
Ephemeral lifecycle ¶
A configuration initializes subsystems and is then discarded: a caller loads it, constructs subsystems from its values, and lets it go. Runtime code holds the values it needs, not the configuration.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EnvName ¶
EnvName composes an environment-variable name from a prefix and parts: each segment upper-cases, runs of characters outside A-Z and 0-9 collapse to single underscores, and empty segments drop out, so EnvName("app", "db", "host") is "APP_DB_HOST" and a caller can vary the prefix freely.
func Load ¶
Load reads the layered configuration files opts names — base, environment overlay, secrets, secrets overlay, later files winning — merges each one that exists onto a zero value of T, finalizes the result, and returns it. A missing file is skipped; a read failure, malformed JSON, a malformed overlay pattern, or a Finalize error stops the load.
func SetDurationFromEnv ¶ added in v0.4.0
SetDurationFromEnv reads the environment variable name and, when it is set, parses it as a Duration and points dest at the result. An unset variable or an empty name leaves dest untouched; a value Duration.Set rejects fails with an error naming the variable. Capability configurations call it from their Finalize env pass for each tri-state duration field.
Types ¶
type Config ¶
Config is the contract a configuration type's pointer implements to take part in Load: Merge overlays another instance's set fields onto the receiver, and Finalize composes its environment override names from the prefix, applies defaults, reads the overrides, and validates.
type Duration ¶
Duration is a time.Duration that takes part in JSON configuration: it unmarshals from the string form time.ParseDuration accepts ("1m30s") or from a bare integer number of nanoseconds, and marshals as the string form.
func (Duration) MarshalJSON ¶
MarshalJSON encodes the duration as its string form.
func (*Duration) Set ¶
Set parses value with time.ParseDuration and stores the result. An empty value is a no-op, so an unset environment variable leaves the receiver unchanged.
func (*Duration) UnmarshalJSON ¶
UnmarshalJSON decodes a duration string, a bare integer number of nanoseconds, or null, which leaves the value unchanged. A fractional number is rejected toward the string form.
type Options ¶
type Options struct {
// Dir is the directory the files are read from; "." when empty.
Dir string
// EnvPrefix is the prefix the loaded configuration's Finalize composes
// its environment-variable names from; empty disables environment
// overrides.
EnvPrefix string
// EnvVar names the environment variable whose value selects the overlay
// environment. Empty, or naming an unset variable, skips both overlays.
EnvVar string
// BaseName is the base file name; "config.json" when empty.
BaseName string
// SecretsName is the secrets file name; "secrets.json" when empty.
SecretsName string
// OverlayPattern produces an overlay name from a file's stem and the
// environment; "%s.%s.json" when empty.
OverlayPattern string
}
Options locates and names the files Load reads. The zero value reads config.json and secrets.json from the current directory, with no environment overlays and no environment overrides.