Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Env references & resolved config

env()

A workspace author wraps a value with env("NAME") instead of reading process.env directly at module-eval time. This keeps the pipeline declaration — and anything that introspects PipelineRegistry before the engine resolves it — free of resolved secrets:

import { env, isEnvRef } from "@health-samurai/interbox";

env("AIDBOX_CLIENT_SECRET");        // => { $env: "AIDBOX_CLIENT_SECRET" }
isEnvRef(env("X"));          // => true
isEnvRef("literal-value");   // => false
interface EnvRef { readonly $env: string; readonly $default?: string }
function env(name: string, fallback?: string): EnvRef;  // fallback = default when unset
function isEnvRef(value: unknown): value is EnvRef;

The engine resolves every EnvRef against its own process environment when it builds the runner config — a workspace author never resolves one by hand.

Authoring types: Str / Num

Config fields that may be supplied either literally or via env() are typed with these two unions instead of string/number:

type Str = string | EnvRef;
type Num = number | EnvRef;

You’ll see these on every built-in config — e.g. MllpSourceConfig.port: Num, AidboxSenderConfig.url: Str (see /builtins).

Resolved<T>

A mapped type that strips every EnvRef branch out of an authoring config, recursively — Str collapses to string, Num to number, arrays and nested objects are walked:

type Resolved<T> = T extends EnvRef
  ? never
  : T extends readonly (infer U)[]
    ? Resolved<U>[]
    : T extends object
      ? { [K in keyof T]: Resolved<T[K]> }
      : T;

This lets the engine derive its own factory config type from the SDK’s authoring config type (Resolved<MllpSourceConfig>, for instance) instead of hand-maintaining a second, parallel “resolved” interface that could drift from the authoring one.