envil envil Docs

Schema Helpers

Defaults, optionality, redaction, JSON parsing, and variable sources.

withDefault

Uses a decoded default when the runtime value is absent:

values: {
  PORT: port.pipe(withDefault(3000)),
}

The data-first form is also supported:

values: {
  PORT: withDefault(port, 3000),
}

The output type does not include undefined.

optional

Allows a missing value and includes undefined in the output type:

values: {
  TRACE_ENDPOINT: optional(url),
}

redacted

Wraps decoded values with Effect Redacted:

import { Effect, Redacted } from "effect";

const appEnv = createEnv(
  server(
    {
      API_SECRET: redacted(requiredString),
    },
    {
      runtimeEnv: { API_SECRET: "secret" },
    },
  ),
);

const env = Effect.runSync(appEnv.server);
const secret = Redacted.value(env.API_SECRET);

Redacted schemas are server-only. Resolver-backed schemas are redacted automatically and do not need this helper.

json

Parses a JSON string and validates the parsed value:

import { Schema } from "effect";

values: {
  FEATURE_FLAGS: json(
    Schema.Struct({
      darkMode: Schema.Boolean,
      newUI: Schema.Boolean,
    }),
  ),
}

fromEnv

Maps one property to an exact runtime environment name:

values: {
  POSTHOG_API_KEY: optional(requiredString).pipe(
    fromEnv("PUBLIC_POSTHOG_API_KEY"),
  ),
}

Use the fragment’s prefix when every variable follows the same naming convention. Use fromEnv for exceptions.

fromResolver

Makes one configured resolver the authoritative source:

values: {
  STRIPE_API_KEY: requiredString.pipe(
    fromResolver(aws, "production/stripe#api-key"),
  ),
}

Source combinators are terminal variable definitions. TypeScript rejects later schema combinators and a second fromEnv or fromResolver, so source metadata cannot disappear during composition.

Note

fromEnv and fromResolver do not change schema decoding. They describe where the unknown input comes from when the Effect runs.