Skip to content

loadConfig

loadConfig<T>(options): Promise<T>

Defined in: load-config.ts:63

Load and validate config from one or more sources.

Sources are loaded in parallel, then merged in array order. Flat ConfigSources merge key-by-key (last wins); StructuredSources deep-merge their nested object (plain objects merge recursively, arrays and primitives replace). The merged object is passed through the schema, which is responsible for coercion (string → number/boolean), validation, and defaults. Use Zod’s z.coerce.* helpers for env vars.

On validation failure, this function throws by default. Pass mode: "warn" to downgrade to a logged warning and receive the unvalidated merged input. The error message identifies the failing keys but not their values by default — environment variables frequently contain secrets, and a thrown error often ends up in logs. Set includeValuesInErrors: true if you’re sure your config doesn’t carry sensitive data, or pass onValidationError to render your own message.

T

LoadConfigOptions<T>

Promise<T>

import { z } from "zod";
import { loadConfig, processEnvSource, dotenvFileSource } from "@arshad-shah/config-kit";
const config = await loadConfig({
schema: z.object({
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
PORT: z.coerce.number().int().positive().default(3000),
DATABASE_URL: z.string().url(),
}),
sources: [
dotenvFileSource(".env"),
dotenvFileSource(".env.local"),
processEnvSource(),
],
});
config.PORT; // number, fully typed
import { loadConfig, configFileSource, objectSource } from "@arshad-shah/config-kit";
const config = await loadConfig({
schema: ConfigSchema,
sources: [
objectSource(defaults), // deep-merged defaults layer
configFileSource({ name: "app" }), // app.config.{ts,js,mjs,cjs,json}
],
mode: process.env.STRICT === "0" ? "warn" : "strict",
onValidationError: (err) => formatConfigError(err),
});