Skip to content

@btravstack/config


@btravstack/config

Classes

ConfigFieldInvalid

Defined in: packages/config/src/config.ts:76

Why one variable's value is not the value a field wanted — the message ConfigInvalid reports against it.

Extends

  • TaggedErrorInstance<"ConfigFieldInvalid", { reason: string; }>

Constructors

Constructor
ts
new ConfigFieldInvalid(args): ConfigFieldInvalid;

Defined in: node_modules/.pnpm/unthrown@5.8.0/node_modules/unthrown/dist/index.d.mts:2034

Parameters
ParameterType
argsobject & object
Returns

ConfigFieldInvalid

Inherited from
ts
TaggedError("ConfigFieldInvalid")<{
  readonly reason: string;
}>.constructor

Properties

PropertyModifierTypeOverridesInherited fromDefined in
_tagreadonly"ConfigFieldInvalid"-TaggedError("ConfigFieldInvalid")._tagnode_modules/.pnpm/unthrown@5.8.0/node_modules/unthrown/dist/index.d.mts:2011
cause?publicunknown-TaggedError("ConfigFieldInvalid").causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
messagepublicstringTaggedError("ConfigFieldInvalid").message-packages/config/src/config.ts:79
namepublicstring-TaggedError("ConfigFieldInvalid").namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
reasonreadonlystring-TaggedError("ConfigFieldInvalid").reasonpackages/config/src/config.ts:77
stack?publicstring-TaggedError("ConfigFieldInvalid").stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076

ConfigInvalid

Defined in: packages/config/src/config.ts:35

A configuration port could not be bound: the environment is wrong, not the code. runMain maps it to sysexits(3)'s EX_CONFIG (78) rather than the generic startup 1, and its message names every offending variable.

Extends

  • TaggedErrorInstance<"ConfigInvalid", { issues: readonly ConfigIssue[]; port: string; }>

Constructors

Constructor
ts
new ConfigInvalid(args): ConfigInvalid;

Defined in: node_modules/.pnpm/unthrown@5.8.0/node_modules/unthrown/dist/index.d.mts:2034

Parameters
ParameterType
argsobject & object
Returns

ConfigInvalid

Inherited from
ts
TaggedError("ConfigInvalid")<{
  readonly port: string;
  readonly issues: readonly ConfigIssue[];
}>.constructor

Properties

PropertyModifierTypeOverridesInherited fromDefined in
_tagreadonly"ConfigInvalid"-TaggedError("ConfigInvalid")._tagnode_modules/.pnpm/unthrown@5.8.0/node_modules/unthrown/dist/index.d.mts:2011
cause?publicunknown-TaggedError("ConfigInvalid").causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
issuesreadonlyreadonly ConfigIssue[]-TaggedError("ConfigInvalid").issuespackages/config/src/config.ts:37
messagepublicstringTaggedError("ConfigInvalid").message-packages/config/src/config.ts:39
namepublicstring-TaggedError("ConfigInvalid").namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
portreadonlystring-TaggedError("ConfigInvalid").portpackages/config/src/config.ts:36
stack?publicstring-TaggedError("ConfigInvalid").stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076

Env

Defined in: packages/config/src/config.ts:19

The environment, as a service. The kernel provides this port to every graph it boots — process.env by default, StartOptions.env for a test — so nothing else in an application touches process.env.

Extends

  • PortInstance<"Env", Readonly<Record<string, string | undefined>>>

Constructors

Constructor
ts
new Env(): Env;

Defined in: packages/di/dist/index.d.mts:16

Returns

Env

Inherited from
ts
Port("Env")<Environment>.constructor

Properties

PropertyModifierTypeInherited fromDefined in
[ID]readonly"Env"Port("Env").[ID]packages/di/dist/index.d.mts:12
[SERVICE]readonlyServicePort("Env").[SERVICE]packages/di/dist/index.d.mts:13
portIdreadonly"Env"Port("Env").portIdpackages/di/dist/index.d.mts:17

Type Aliases

ConfigField

ts
type ConfigField<T> = object;

Defined in: packages/config/src/config.ts:92

One environment variable, read into a value: parse receives the raw string (or undefined when unset) and answers the value or the reason it is not one. Compose them with Config.object.

check is the same field's rule applied to a value that is ALREADY a T — a pin, or a default — so the two routes into a configuration cannot disagree about what is valid. It is optional: a hand-written field keeps compiling and simply accepts whatever it is handed.

Type Parameters

Type Parameter
T

Properties

PropertyModifierTypeDefined in
check?readonly(value) => Result<T, ConfigFieldInvalid>packages/config/src/config.ts:95
parsereadonly(raw) => Result<T, ConfigFieldInvalid>packages/config/src/config.ts:94
variablereadonlystringpackages/config/src/config.ts:93

ConfigIssue

ts
type ConfigIssue = object;

Defined in: packages/config/src/config.ts:25

The one issue shape a configuration schema reports: Standard Schema's Issue, restated structurally so this package depends on nothing.

Properties

PropertyModifierTypeDefined in
messagereadonlystringpackages/config/src/config.ts:26
path?readonlyReadonlyArray< | PropertyKey | { key: PropertyKey; }>packages/config/src/config.ts:27

ConfigSchema

ts
type ConfigSchema<Input, Output> = object;

Defined in: packages/config/src/config.ts:58

The slice of Standard Schema (v1) this package speaks — structurally, so a zod, valibot or arktype schema is accepted with no adapter, and so is anything Config.object builds.

Type Parameters

Type Parameter
Input
Output

Properties

PropertyModifierTypeDefined in
~standardreadonlyobjectpackages/config/src/config.ts:59
~standard.types?readonlyobjectpackages/config/src/config.ts:71
~standard.types.inputreadonlyInputpackages/config/src/config.ts:71
~standard.types.outputreadonlyOutputpackages/config/src/config.ts:71
~standard.validatereadonly(value) => | { issues?: undefined; value: Output; } | { issues: readonly ConfigIssue[]; } | Promise< | { issues?: undefined; value: Output; } | { issues: readonly ConfigIssue[]; }>packages/config/src/config.ts:62
~standard.vendorreadonlystringpackages/config/src/config.ts:61
~standard.versionreadonly1packages/config/src/config.ts:60

Environment

ts
type Environment = Readonly<Record<string, string | undefined>>;

Defined in: packages/config/src/config.ts:12

The process environment as it actually arrives: flat, and every value a string or absent.

Variables

Config

ts
const Config: object;

Defined in: packages/config/src/config.ts:190

Configuration, the twelve-factor way: typed values bound from the environment, validated once as the graph is built, and injected like any other service.

Config.object({...}) describes a slice of the environment as a schema — any Standard Schema does as well — and Config.provider(Port)(schema) turns it into a provider that reads Env and answers ConfigInvalid.

Type Declaration

NameTypeDefault valueDescriptionDefined in
boolean()(variable, options) => ConfigField<boolean>-A flag: true/false, 1/0, yes/no or on/off, case-insensitive. Anything else is an error rather than a falsy reading — a deployment that wrote HTTP_COMPRESSION=enabled meant to turn it on.packages/config/src/config.ts:226
integer()(variable, options) => ConfigField<number>-A whole number, optionally bounded (both bounds inclusive).packages/config/src/config.ts:210
list()(variable, options) => ConfigField<readonly string[]>-A comma-separated list, each entry trimmed and empty entries dropped, so "a, b," is ["a", "b"]. min (default 1) is the floor a shorter list is named against — a variable that lists nothing is a deployment mistake, not an empty list.packages/config/src/config.ts:251
object()<F>(fields) => ConfigSchema<Readonly<Record<string, string | undefined>>, { readonly [K in string | number | symbol]: F[K] extends ConfigField<T> ? T : never }>-A record of fields, as a Standard Schema over the environment. Every field is read, so one validation names every offending variable at once — an operator fixes the deployment in one round trip.packages/config/src/config.ts:299
parse()<Output>(port, schema) => (env) => AsyncResult<Output, ConfigInvalid>-Validates env against schema; the issues become one ConfigInvalid naming port. This is the step Config.provider performs, on its own — for a piece that is already its own provider and has no second port to hang a Config.provider on, such as a starter binding its options inside a make arm.packages/config/src/config.ts:346
pinned()<T>(value, field) => ConfigField<T>-field, unless value is given — then a field answering value and reading nothing. Explicit beats environment beats default, per field: http({ port: 0 }) still reads HOST. The pin is CHECKED against the field's own rule, so a value the deployment route would refuse is refused here too, with the same message. Without that, a pinned NaN body limit turned a trust boundary off in silence — size > NaN is false — and the composition root was the one input to the configuration system nothing validated.packages/config/src/config.ts:285
port()(variable, options) => ConfigField<number>-A TCP port: a whole number the OS will accept, 0 (an ephemeral bind) included.packages/config/src/config.ts:271
provider(){ <P> (port): (schema) => Provider<InstanceType<P>, ConfigInvalid, Env> & object; <Name> (name): <Output>(schema) => Provider<PortInstance<Name, Output>, ConfigInvalid, Env> & object; }configProviderA provider binding a port from the environment through schema. Reads Env, so the port is built with the rest of the graph and a bad environment is a modeled startup Err rather than a silently wrong value. Two forms of the first call. Config.provider(Port)(schema) binds a port you declared — for a port that is public API another package names. Config.provider("RelayConfig")(schema) mints the port and hands back the provider carrying it, for a slice that is one application's own.packages/config/src/config.ts:365
string()(variable, options) => ConfigField<string>-A non-empty string — a rule about the RAW value, deliberately not a check: "set but empty" is a deployment mistake, where a pinned "" is a decision. http({ cors: false }) pins exactly that, and an off switch spelled as the empty string must not be refused as a blank variable. Remarks The bound value is trimmed. X=" abc " binds "abc", because every field parses the trimmed string — it is what makes a whitespace-only variable "set but empty" rather than a value, and what stops a stray space from turning a port into a parse error. A secret whose whitespace is significant is therefore the one value this field cannot carry: pin it through the composition root instead, where Config.pinned hands the value over untouched.packages/config/src/config.ts:206
url()(variable, options) => ConfigField<string>-A URL, kept as the string it was written as. The value is what a consumer hands to new URL, and this is what stops that construction from throwing: a malformed one is a ConfigInvalid naming the variable, at graph build, rather than a Defect from wherever the URL is finally needed.packages/config/src/config.ts:242

Released under the MIT License.