Skip to main content
Wrap a config-field schema so it falls back to an environment variable when the field is omitted. Precedence is explicit value > env var > the inner schema’s own default/required check:
  • An explicit value (anything other than undefined) is passed straight through — a caller-supplied config always wins over the environment.
  • When the field is undefined, process.env[envKey] is substituted. An env var set to the empty string is treated as unset (a common deploy footgun) so it doesn’t satisfy a .min(1) by accident.
  • The inner schema then validates the resolved value, keeping its exact semantics — regex, .min(1), .url(), .optional(), .default(...). When both the field and the env var are absent, a required inner schema raises its normal “required” error.
The output type is the inner schema’s output type, so call sites are unchanged. Because substitution only happens on undefined, wrapping a field inside a z.object leaves it a plain key on the parsed result — union discriminators like "accessToken" in config keep working.