first commit
This commit is contained in:
184
docs/foundation/core/config/README.md
Normal file
184
docs/foundation/core/config/README.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# @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.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [config-builder](./src/core/config-builder/config-builder.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [config-builder](./src/core/config-builder/config-builder.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [config-store](./src/core/config-store/config-store.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [config-store](./src/core/config-store/config-store.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [cli-layer](./src/layers/cli-layer/cli-layer.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [cli-layer](./src/layers/cli-layer/cli-layer.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [defaults-layer](./src/layers/defaults-layer/defaults-layer.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [defaults-layer](./src/layers/defaults-layer/defaults-layer.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [env-layer](./src/layers/env-layer/env-layer.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [env-layer](./src/layers/env-layer/env-layer.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [file-layer](./src/layers/file-layer/file-layer.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [file-layer](./src/layers/file-layer/file-layer.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [object-layer](./src/layers/object-layer/object-layer.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [object-layer](./src/layers/object-layer/object-layer.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [common](./src/types/common.md) — This module defines every public TypeScript interface and type alias used across the `@suaveplan/config` package. It is…
|
||||
- [schemas](./src/types/schemas.md) — This module exposes Zod schemas for every public options interface in `@suaveplan/config`. Using these schemas, callers…
|
||||
- [mask](./src/utils/mask.md) — This module provides low-level dot-notation path traversal utilities (`getByPath`, `setByPath`, `hasByPath`) and the `m…
|
||||
- [merge](./src/utils/merge.md) — This module provides two functions that form the merge backbone of the config pipeline: `deepMerge` performs a structur…
|
||||
<!-- end:auto-docs --> - [config-builder](./src/core/config-builder/config-builder.md) — <!-- begin:auto-docs --> _(no submodules)_- [config-store](./src/core/config-store/config-store.md) — <!-- begin:auto-docs --> _(no submodules)_- [config-store](./src/core/config-store/config-store.md) — <!-- begin:auto-docs --> _(no submodules)_- [cli-layer](./src/layers/cli-layer/cli-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [cli-layer](./src/layers/cli-layer/cli-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [defaults-layer](./src/layers/defaults-layer/defaults-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [defaults-layer](./src/layers/defaults-layer/defaults-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [env-layer](./src/layers/env-layer/env-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [env-layer](./src/layers/env-layer/env-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [file-layer](./src/layers/file-layer/file-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [file-layer](./src/layers/file-layer/file-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [object-layer](./src/layers/object-layer/object-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [object-layer](./src/layers/object-layer/object-layer.md) — <!-- begin:auto-docs --> _(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](./src/types/schemas.md) — This module exposes Zod schemas for every public options interface in `@suaveplan/config`. Using these schemas, callers…
|
||||
- [mask](./src/utils/mask.md) — This module provides low-level dot-notation path traversal utilities (`getByPath`, `setByPath`, `hasByPath`) and the `m…
|
||||
- [merge](./src/utils/merge.md) — 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) — <!-- begin:auto-docs --> _(no submodules)_- [config-store](./src/core/config-store/config-store.md) — <!-- begin:auto-docs --> _(no submodules)_- [config-store](./src/core/config-store/config-store.md) — <!-- begin:auto-docs --> _(no submodules)_- [cli-layer](./src/layers/cli-layer/cli-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [cli-layer](./src/layers/cli-layer/cli-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [defaults-layer](./src/layers/defaults-layer/defaults-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [defaults-layer](./src/layers/defaults-layer/defaults-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [env-layer](./src/layers/env-layer/env-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [env-layer](./src/layers/env-layer/env-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [file-layer](./src/layers/file-layer/file-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [file-layer](./src/layers/file-layer/file-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [object-layer](./src/layers/object-layer/object-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [object-layer](./src/layers/object-layer/object-layer.md) — <!-- begin:auto-docs --> _(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](./src/types/schemas.md) — This module exposes Zod schemas for every public options interface in `@suaveplan/config`. Using these schemas, callers…
|
||||
- [mask](./src/utils/mask.md) — This module provides low-level dot-notation path traversal utilities (`getByPath`, `setByPath`, `hasByPath`) and the `m…
|
||||
- [merge](./src/utils/merge.md) — 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) — <!-- begin:auto-docs --> _(no submodules)_- [config-store](./src/core/config-store/config-store.md) — <!-- begin:auto-docs --> _(no submodules)_- [config-store](./src/core/config-store/config-store.md) — <!-- begin:auto-docs --> _(no submodules)_- [cli-layer](./src/layers/cli-layer/cli-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [cli-layer](./src/layers/cli-layer/cli-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [defaults-layer](./src/layers/defaults-layer/defaults-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [defaults-layer](./src/layers/defaults-layer/defaults-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [env-layer](./src/layers/env-layer/env-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [env-layer](./src/layers/env-layer/env-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [file-layer](./src/layers/file-layer/file-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [file-layer](./src/layers/file-layer/file-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [object-layer](./src/layers/object-layer/object-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [object-layer](./src/layers/object-layer/object-layer.md) — <!-- begin:auto-docs --> _(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](./src/types/schemas.md) — This module exposes Zod schemas for every public options interface in `@suaveplan/config`. Using these schemas, callers…
|
||||
- [mask](./src/utils/mask.md) — This module provides low-level dot-notation path traversal utilities (`getByPath`, `setByPath`, `hasByPath`) and the `m…
|
||||
- [merge](./src/utils/merge.md) — 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) — <!-- begin:auto-docs --> _(no submodules)_- [config-store](./src/core/config-store/config-store.md) — <!-- begin:auto-docs --> _(no submodules)_ - [config-store](./src/core/config-store/config-store.md) — <!-- begin:auto-docs --> _(no submodules)_- [cli-layer](./src/layers/cli-layer/cli-layer.md) — <!-- begin:auto-docs --> _(no submodules)_ - [cli-layer](./src/layers/cli-layer/cli-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [defaults-layer](./src/layers/defaults-layer/defaults-layer.md) — <!-- begin:auto-docs --> _(no submodules)_ - [defaults-layer](./src/layers/defaults-layer/defaults-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [env-layer](./src/layers/env-layer/env-layer.md) — <!-- begin:auto-docs --> _(no submodules)_ - [env-layer](./src/layers/env-layer/env-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [file-layer](./src/layers/file-layer/file-layer.md) — <!-- begin:auto-docs --> _(no submodules)_ - [file-layer](./src/layers/file-layer/file-layer.md) — <!-- begin:auto-docs --> _(no submodules)_- [object-layer](./src/layers/object-layer/object-layer.md) — <!-- begin:auto-docs --> _(no submodules)_ - [object-layer](./src/layers/object-layer/object-layer.md) — <!-- begin:auto-docs --> _(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](./src/types/schemas.md) — This module exposes Zod schemas for every public options interface in `@suaveplan/config`. Using these schemas, callers…
|
||||
- [mask](./src/utils/mask.md) — This module provides low-level dot-notation path traversal utilities (`getByPath`, `setByPath`, `hasByPath`) and the `m…
|
||||
- [merge](./src/utils/merge.md) — This module provides two functions that form the merge backbone of the config pipeline: `deepMerge` performs a structur…
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
bun add @suaveplan/config
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```ts
|
||||
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`](src/types/common.md) | All public TypeScript interfaces and type aliases |
|
||||
| [`src/types/schemas.md`](src/types/schemas.md) | Zod option schemas for runtime validation |
|
||||
| [`src/core/config-builder/config-builder.md`](src/core/config-builder/config-builder.md) | `createConfig` orchestrator |
|
||||
| [`src/core/config-store/config-store.md`](src/core/config-store/config-store.md) | `createConfigStore` static store factory |
|
||||
| [`src/layers/defaults-layer/defaults-layer.md`](src/layers/defaults-layer/defaults-layer.md) | Static default values layer |
|
||||
| [`src/layers/object-layer/object-layer.md`](src/layers/object-layer/object-layer.md) | In-memory config object layer |
|
||||
| [`src/layers/env-layer/env-layer.md`](src/layers/env-layer/env-layer.md) | Environment variable layer + `coerceValue` |
|
||||
| [`src/layers/file-layer/file-layer.md`](src/layers/file-layer/file-layer.md) | Pre-parsed file content layer with watch mode |
|
||||
| [`src/layers/cli-layer/cli-layer.md`](src/layers/cli-layer/cli-layer.md) | CLI argument layer + `parseArgs` |
|
||||
| [`src/utils/merge.md`](src/utils/merge.md) | `deepMerge` and `mergeLayers` utilities |
|
||||
| [`src/utils/mask.md`](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._
|
||||
|
||||
Reference in New Issue
Block a user