Config Kit
Typed, validated environment config loading with Zod.
Quick Start
Section titled “Quick Start”import { loadConfig, envBool, envPort, envEnum, z } from '@iskra-bun/config-kit';
const config = loadConfig({ schema: z.object({ DATABASE_URL: z.string().url(), PORT: envPort, DEBUG: envBool, NODE_ENV: envEnum(['development', 'production', 'test'] as const), }),});Bun auto-loads .env into process.env; loadConfig reads it by default with no extra setup.
loadConfig
Section titled “loadConfig”function loadConfig<TSchema extends z.ZodTypeAny>(options: { schema: TSchema; source?: Record<string, string | undefined>;}): z.output<TSchema>- Validates
source(defaults toprocess.env) against the Zod schema. - Returns a typed, deep-frozen (fully immutable) config object.
- On failure: throws
ConfigErrorlisting every invalid or missing field by name and reason — never exposing secret values.
Coercers
Section titled “Coercers”Coercers transform string env vars to the correct type with clear error messages.
envBool
Section titled “envBool”Accepts "true"/"1"/"yes" → true and "false"/"0"/"no" → false.
const schema = z.object({ FEATURE_X: envBool });envNumber
Section titled “envNumber”Coerces any numeric string to number (integer or decimal).
const schema = z.object({ TIMEOUT_MS: envNumber });envPort
Section titled “envPort”Coerces to an integer number between 1 and 65535.
const schema = z.object({ PORT: envPort });envEnum
Section titled “envEnum”Restricts the value to a list of string literals.
const schema = z.object({ LOG_LEVEL: envEnum(['debug', 'info', 'warn', 'error'] as const),});fromEnv: a kit’s section from your variable names
Section titled “fromEnv: a kit’s section from your variable names”Each kit reads its section of app.config (oracle, kv, db…) with its own keys. fromEnv() builds that section from the environment variables a service already has, so migrating it does not rename them:
import { env, envEnum, envNumber, envPort, fromEnv } from '@iskra-bun/config-kit';
export default { oracle: fromEnv({ host: 'DB_HOST_ORACLE', // a name alone: text, required port: env('DB_PORT_ORACLE', envPort, { default: 1521 }), serviceName: env(['DB_SERVICE_ORACLE', 'ORA_SERVICE']), // the first one set wins user: 'DB_USER_ORACLE', password: 'DB_PASS_ORACLE', pool: { max: env('DB_POOL_MAX', envNumber, { default: 4 }) }, }), kv: fromEnv({ driver: env('KV_DRIVER', envEnum(['memory', 'redis']), { default: 'redis' }), connection: 'REDIS_URL' }),};env(names, parser?, { default } | { optional: true }): the variable (or the first set of several: a new name, then the legacy one; an empty value counts as unset), converted by a coercer or any Zod schema of a string. Without a value and withoutdefaulta field is an error, unlessoptional, which leaves its key out.- The section is typed from the spec, and each kit still validates its own section when it starts.
- Every problem comes at once in a
ConfigErrorthat names the variables (DB_HOST_ORACLE is not set,DB_PORT_ORACLE: Expected a port number), never their values.
Error Handling
Section titled “Error Handling”loadConfig throws ConfigError (from @iskra-bun/core) with all problems in a single message:
Config validation failed: • DATABASE_URL: Invalid url • PORT: Expected a port number (1–65535), received "99999" • NODE_ENV: Expected one of ["development", "production", "test"], received "staging"Field values are never included in the error message (secret protection).
Environment Variables
Section titled “Environment Variables”DATABASE_URL=postgres://localhost:5432/mydbPORT=3000DEBUG=trueNODE_ENV=production