Config
A tiny configuration tree, the way every framework should ship one. Drop a tree of values in once at boot, then read them by dotted path from anywhere in your app. Think Laravel’s config(...) helper — a 30-line module with one runtime dep. Deliberately minimal — for reactive subscriptions, layer on @mongez/atom.
Highlighted features
Dotted-path reads
config.get(“api.url”), config.get(“servers.0.host”) — TypeScript-typed paths, default fallbacks for missing keys.
Deep-merge writes
config.set(partial) deep-merges into the existing tree — feature flags, environment overrides, and bootstrap blocks compose without clobbering.
Process-wide singleton
One tree per process, importable from anywhere. No provider, no React context, no plumbing.
~30 lines, 1 dep
Intentionally tiny. @mongez/reinforcements for path utilities, nothing else. No events, no clone-on-read, no diffing — exactly the right surface for a config bag.
Install
npm install @mongez/configyarn add @mongez/configpnpm add @mongez/config@mongez/reinforcements is bundled as a regular dep — no peer install needed.
Quick peek
import config from "@mongez/config";
config.set({ api: { url: "https://api.example.com", timeout: 5000 }, features: { darkMode: true, beta: false },});
config.get("api.url"); // "https://api.example.com"config.get("api.timeout", 30000); // 5000 (fallback ignored)config.get("missing.path", "fallback"); // "fallback"Seed once at boot, read by dotted path with a fallback from anywhere.
The three methods
| Method | Purpose |
|---|---|
config.set(obj) | Deep-merge a partial tree into existing data |
config.set(path, value) | Write one value at a dotted path; creates intermediate containers on demand |
config.get(path, default?) | Read by dotted path, substituting default for missing or undefined results |
config.list() | Return the entire data object by live reference |
Scope boundaries
| Concern | Lives in | Why |
|---|---|---|
| Reactive config / subscriptions | @mongez/atom | Keep the core config dumb |
| Per-request SSR isolation | @mongez/atom (AtomStore) | This is a singleton; not isolation-aware |
Path utilities (get, set, merge) | @mongez/reinforcements | Used internally |
Watch-outs
- No clone on read.
list()returns the same object reference every time. Mutating it mutates the live config. - No event when values change. Set, then read. Nothing fires.
- Deep merge is the only composition rule. Repeated writes to the same path just overwrite the leaf.
These are deliberate choices to keep the surface minimal. For anything reactive, layer on @mongez/atom.