Skip to main content

Env Inputs

Read typed environment variables with literal unions, field-level sensitive schema annotations, Decode<T> boundary decoding, and environment-aware overrides.

Source

examples/env-inputs/main.rank
/// Shows std::Env with explicit Decode<T> at the env boundary, field-level
/// sensitive schema annotations, defaults, and environment-specific overrides.

use std::Decode
use std::Env

AppEnv = `dev` | `staging` | `prod`
LogLevel = `debug` | `info` | `warn` | `error`
Port = 8080 | 8443 | 9000

SysEnv = Object {
APP_ENV: AppEnv,
PORT?: Decode<Port>,
LOG_LEVEL?: LogLevel,
@sensitive
SECRET_KEY: string,
...: string,
}

AppConfig = Object {
env: AppEnv,
port: number,
logLevel: LogLevel,
debug: bool,
baseUrl: string,
}

env = Env<SysEnv> {}

port: number = env.PORT ?? 8080

base_config: AppConfig = {
env: env.APP_ENV,
port: port,
logLevel: env.LOG_LEVEL ?? (env.APP_ENV == `prod` ? `warn` : `debug`),
debug: env.APP_ENV == `dev`,
baseUrl: `http://localhost:${port}`,
}

config: AppConfig = env.APP_ENV == `prod`
? base_config with { baseUrl: `https://api.example.com` }
: base_config

pub main = || config

Output

// APP_ENV=prod PORT=8443 LOG_LEVEL=warn SECRET_KEY=abc123
{
"env": "prod",
"port": 8443,
"logLevel": "warn",
"debug": false,
"baseUrl": "https://api.example.com"
}

Key concepts

  • Literal env schemaAPP_ENV and LOG_LEVEL are constrained to finite unions before the rest of the program runs, and PORT is decoded to a numeric union at the boundary.
  • Required vs optional varsAPP_ENV and SECRET_KEY must be present, while PORT and LOG_LEVEL can safely fall back.
  • Field-level sensitive schema annotationSECRET_KEY carries @sensitive on the type field itself, so the env boundary can redact the secret without needing a separate sensitive binding.
  • Decode<T> + ??PORT?: Decode<Port> turns host text into a typed numeric value at the env boundary, and ?? supplies the default when the variable is absent.
  • with for environment-specific shape — the production branch overrides only baseUrl, leaving the rest of the typed object unchanged.

Run it

APP_ENV=dev SECRET_KEY=mysecret rank examples/env-inputs
APP_ENV=prod PORT=8443 LOG_LEVEL=warn SECRET_KEY=mysecret rank examples/env-inputs