API reference@evolu/commonConfig › env

function env<Props>(
  props: Props,
  ..._validation: [EnvValidation<Props>] extends [never]
    ? []
    : [EnvValidation<Props>]
): EnvType<Props>;

Defined in: packages/common/src/Config.ts:170

Creates a reversible environment-variable codec with a flat decoded output.

Declare camelCase fields directly, or put them in one-level CONSTANT_CASE namespace groups. A direct port field reads PORT; a maxOwnerBytes field in an EVOLU_RELAY group reads EVOLU_RELAY_MAX_OWNER_BYTES. Groups affect external names only. Duplicate decoded fields or encoded names are rejected during construction, even when their Types are identical.

Selects exact declared unprefixed names and all keys within declared namespaces. Namespace selection ignores casing so incorrectly cased names fail validation instead of being ignored. Selected names must match their exact declared spelling. Unrelated variables are ignored; misspelled unprefixed names or namespace prefixes can therefore still look absent.

Field Types must encode to strings. Optional fields may be absent, but explicit undefined values are rejected. Empty strings remain present and must satisfy the field Type. Compose withDefault to supply defaults. Encoding emits canonical external names and string values, preserving absence when the field codec does. Errors retain external names and nested paths.

Reads own string properties from any non-null object, including process.env. Selected properties must be enumerable data properties; getters are never read. Prototypes and internal contents such as Map entries are ignored. Non-object inputs fail with standard object errors. Schema names must satisfy EnvName; groups cannot be nested. Loading and source precedence remain explicit application code.

Example

import {
  assertEqual,
  assertErr,
  assertOk,
  assertType,
  ByteSizeLiteral,
  env,
  optional,
  Port,
  PortFromString,
  withDefault,
} from "@evolu/common";

const RelayEnv = env({
  port: withDefault(optional(PortFromString), Port.orThrow(4000)),
  EVOLU_RELAY: {
    maxOwnerBytes: optional(ByteSizeLiteral),
  },
});

const result = RelayEnv.fromUnknown({
  PORT: "04000",
  EVOLU_RELAY_MAX_OWNER_BYTES: "512KiB",
  HOME: "/home/evolu",
});

assertOk(result, { port: 4000, maxOwnerBytes: "512KiB" });
assertType<typeof result.value.port, Port>();
assertEqual(RelayEnv.to(result.value), {
  PORT: "4000",
  EVOLU_RELAY_MAX_OWNER_BYTES: "512KiB",
});

assertOk(RelayEnv.fromUnknown({}), { port: 4000 });
assertErr(RelayEnv.fromUnknown({ PORT: "" }));
assertErr(RelayEnv.fromUnknown({ EVOLU_RELAY_MAX_OWENR_BYTES: "1MiB" }));
assertErr(RelayEnv.fromUnknown({ evolu_relay_max_owner_bytes: "1MiB" }));