Files
skills/docs/foundation/core/config
2026-05-29 08:20:56 +01:00
..
2026-05-29 08:20:56 +01:00
2026-05-29 08:20:56 +01:00

@suaveplan/config - Layered configuration management: defaults, file, object, env, CLI layers merged in priority order with deep-merge, Zod validation, OTel instrumentation, and event-bus watch support.

Summary

Layered configuration management for Suaveplan. Resolves an ordered set of typed layers (defaults, file, object, env, CLI) in priority order, deep-merges the results, applies per-environment overrides, validates via a caller-supplied Zod schema or custom function, and exposes an immutable ConfigStore with live reload and event-bus change propagation.

Documentation tree

  • config-builder — (no submodules)
  • config-store — (no submodules)
  • cli-layer — (no submodules)
  • defaults-layer — (no submodules)
  • env-layer — (no submodules)
  • file-layer — (no submodules)
  • object-layer — (no submodules)
  • common — This module defines every public TypeScript interface and type alias used across the @suaveplan/config package. It is…
  • schemas — This module exposes Zod schemas for every public options interface in @suaveplan/config. Using these schemas, callers…
  • mask — This module provides low-level dot-notation path traversal utilities (getByPath, setByPath, hasByPath) and the `m…
  • merge — This module provides two functions that form the merge backbone of the config pipeline: deepMerge performs a structur…
- [config-builder](./src/core/config-builder/config-builder.md) — _(no submodules)_- [config-store](./src/core/config-store/config-store.md) — _(no submodules)_- [config-store](./src/core/config-store/config-store.md) — _(no submodules)_- [cli-layer](./src/layers/cli-layer/cli-layer.md) — _(no submodules)_- [cli-layer](./src/layers/cli-layer/cli-layer.md) — _(no submodules)_- [defaults-layer](./src/layers/defaults-layer/defaults-layer.md) — _(no submodules)_- [defaults-layer](./src/layers/defaults-layer/defaults-layer.md) — _(no submodules)_- [env-layer](./src/layers/env-layer/env-layer.md) — _(no submodules)_- [env-layer](./src/layers/env-layer/env-layer.md) — _(no submodules)_- [file-layer](./src/layers/file-layer/file-layer.md) — _(no submodules)_- [file-layer](./src/layers/file-layer/file-layer.md) — _(no submodules)_- [object-layer](./src/layers/object-layer/object-layer.md) — _(no submodules)_- [object-layer](./src/layers/object-layer/object-layer.md) — _(no submodules)_- [common](./src/types/common.md) — This module defines every public TypeScript interface and type alias used across the `@suaveplan/config` package. It is…
  • schemas — This module exposes Zod schemas for every public options interface in @suaveplan/config. Using these schemas, callers…
  • mask — This module provides low-level dot-notation path traversal utilities (getByPath, setByPath, hasByPath) and the `m…
  • merge — This module provides two functions that form the merge backbone of the config pipeline: deepMerge performs a structur…
  • config-builder — (no submodules)- config-store — (no submodules)- config-store — (no submodules)- cli-layer — (no submodules)- cli-layer — (no submodules)- defaults-layer — (no submodules)- defaults-layer — (no submodules)- env-layer — (no submodules)- env-layer — (no submodules)- file-layer — (no submodules)- file-layer — (no submodules)- object-layer — (no submodules)- object-layer — (no submodules)- common — This module defines every public TypeScript interface and type alias used across the @suaveplan/config package. It is…
  • schemas — This module exposes Zod schemas for every public options interface in @suaveplan/config. Using these schemas, callers…
  • mask — This module provides low-level dot-notation path traversal utilities (getByPath, setByPath, hasByPath) and the `m…
  • merge — This module provides two functions that form the merge backbone of the config pipeline: deepMerge performs a structur…
  • config-builder — (no submodules)- config-store — (no submodules)- config-store — (no submodules)- cli-layer — (no submodules)- cli-layer — (no submodules)- defaults-layer — (no submodules)- defaults-layer — (no submodules)- env-layer — (no submodules)- env-layer — (no submodules)- file-layer — (no submodules)- file-layer — (no submodules)- object-layer — (no submodules)- object-layer — (no submodules)- common — This module defines every public TypeScript interface and type alias used across the @suaveplan/config package. It is…
  • schemas — This module exposes Zod schemas for every public options interface in @suaveplan/config. Using these schemas, callers…
  • mask — This module provides low-level dot-notation path traversal utilities (getByPath, setByPath, hasByPath) and the `m…
  • merge — This module provides two functions that form the merge backbone of the config pipeline: deepMerge performs a structur…
  • config-builder — (no submodules)- config-store — (no submodules) - config-store — (no submodules)- cli-layer — (no submodules) - cli-layer — (no submodules)- defaults-layer — (no submodules) - defaults-layer — (no submodules)- env-layer — (no submodules) - env-layer — (no submodules)- file-layer — (no submodules) - file-layer — (no submodules)- object-layer — (no submodules) - object-layer — (no submodules)- common — This module defines every public TypeScript interface and type alias used across the @suaveplan/config package. It is…
  • schemas — This module exposes Zod schemas for every public options interface in @suaveplan/config. Using these schemas, callers…
  • mask — This module provides low-level dot-notation path traversal utilities (getByPath, setByPath, hasByPath) and the `m…
  • merge — This module provides two functions that form the merge backbone of the config pipeline: deepMerge performs a structur…

Installation

bun add @suaveplan/config

Quick Start

import { createConfig, defaultsLayer, fileLayer, envLayer, cliLayer } from '@suaveplan/config';
import { readFileSync } from 'node:fs';
import z from 'zod';

const Schema = z.object({
  server: z.object({ port: z.number(), host: z.string() }),
  db:     z.object({ url: z.string(), pool: z.number(), password: z.string() }),
  log:    z.object({ level: z.string() }),
});
type AppConfig = z.infer<typeof Schema>;

const store = createConfig<AppConfig>({
  layers: [
    defaultsLayer({ server: { port: 3000, host: '0.0.0.0' }, db: { pool: 5, password: '' }, log: { level: 'info' } }),
    fileLayer({ content: JSON.parse(readFileSync('./config.json', 'utf-8')) }),
    envLayer({ prefix: 'APP_', mapping: { PORT: 'server.port', DB_URL: 'db.url', DB_PASS: 'db.password' } }),
    cliLayer({ args: process.argv.slice(2), mapping: { port: 'server.port' } }),
  ],
  validate: (raw) => Schema.parse(raw),
  sensitive: ['db.password', 'db.url'],
  environments: { production: { log: { level: 'warn' } }, development: { log: { level: 'debug' } } },
  environment: process.env.NODE_ENV ?? 'development',
});

console.log(store.get('server.port')); // number
console.log(store.toMasked());         // db.password = '****'

// Live reload
await store.reload();

// Subscribe to changes
const unsub = store.subscribe((next) => console.log('Config updated:', next));

Module Documentation

Module Description
src/types/common.md All public TypeScript interfaces and type aliases
src/types/schemas.md Zod option schemas for runtime validation
src/core/config-builder/config-builder.md createConfig orchestrator
src/core/config-store/config-store.md createConfigStore static store factory
src/layers/defaults-layer/defaults-layer.md Static default values layer
src/layers/object-layer/object-layer.md In-memory config object layer
src/layers/env-layer/env-layer.md Environment variable layer + coerceValue
src/layers/file-layer/file-layer.md Pre-parsed file content layer with watch mode
src/layers/cli-layer/cli-layer.md CLI argument layer + parseArgs
src/utils/merge.md deepMerge and mergeLayers utilities
src/utils/mask.md Path utilities and maskSensitive

Layer Priorities

Layer Priority Description
defaultsLayer 0 Static baseline — always overridden
fileLayer 10 Pre-parsed file content
objectLayer 20 In-memory programmatic overrides
envLayer 30 Environment variables
cliLayer 40 CLI arguments — highest priority

API

Core

Export Description
createConfig(options) Resolves layers, merges, validates, returns live store
createConfigStore(options) Low-level static store factory

Layers

Export Description
defaultsLayer(defaults) Static defaults at priority 0
fileLayer(options) Pre-parsed file content at priority 10
objectLayer(data, priority?) In-memory object at priority 20
envLayer(options) Environment variables at priority 30
cliLayer(options) CLI arguments at priority 40
parseArgs(args, mapping) Parse raw argv into flag→value map

Utilities

Export Description
deepMerge(base, override) Recursive object merge
mergeLayers(layers) Fold ordered layers with deepMerge
getByPath(obj, path) Read dot-notation path
setByPath(obj, path, value) Write dot-notation path
hasByPath(obj, path) Check dot-notation path existence
maskSensitive(data, paths, mask?) Replace sensitive paths
coerceValue(raw) Convert env-var string to typed value

Error Codes

Code Description
CONFIG.MISSING Required config key not found
CONFIG.INVALID_TYPE Value has wrong type
CONFIG.PARSE_FAILED Layer resolution threw
CONFIG.FILE_NOT_FOUND File layer file not found
CONFIG.ENV_NOT_SET Required env var not set
CONFIG.RELOAD_FAILED Reload aborted or layer threw
CONFIG.VALIDATION_FAILED Validator threw

Dependencies

Package Role
@suaveplan/error SuaveplanError base, defineCodes
@suaveplan/types LoggerLike, EventBusLike
@suaveplan/events EventBus for file-layer watch mode
@suaveplan/env Coercion functions for env-var values
zod Option schemas
@opentelemetry/api Spans, counters, histograms
tslib TypeScript runtime helpers

Benchmarks

Run with bun run bench.

Benchmark Operations / sec (approx.)
createConfig 5 layers (cold) TBD
store.get 100x deeply nested key TBD
mergeLayers 2 layers TBD
mergeLayers 5 layers TBD
mergeLayers 10 layers TBD
mergeLayers 20 layers TBD

Run bun run bench to populate these numbers on your hardware.