xPulse
πŸ‡¬πŸ‡§ EN

@xpulse/config – Component Spec

Status: CONCEPT Β· Updated March 2026 Parent: GLOBAL_concept-ecosystem.md


Overview

Reads and validates xpulse.json, resolves ${ENV_VAR} references, and exposes the configuration via config.get().

One responsibility: know xpulse.json and make it accessible – nothing more.


Dependencies

@xpulse/config
β”œβ”€β”€ @xpulse/dotenv ← load .env before ${VAR} resolution
└── @xpulse/event ← fire config:loaded

API

Loading

import config from '@xpulse/config';
// Loads xpulse.json from the current working directory
await config.load();
// Explicit path
await config.load({ path: '/app/xpulse.json' });

Merge Order

config.load() builds the configuration in three layers:

1. Hardcoded DEFAULTS ← lowest priority
2. node_modules/@xpulse/*/xpulse.json ← merged alphabetically
3. App's own xpulse.json ← highest priority, overrides everything

All installed @xpulse/* packages can ship default configuration that becomes active automatically β€” without the app needing to configure anything. The app's own xpulse.json always takes precedence.

Example: @xpulse/doc ships all docs sources as defaults. To disable one:

{ "docs": { "sources": { "event": { "docs": false } } } }

Standard keys directly

config.name // 'xpulse-web'
config.type // 'tool'

All keys via get()

config.get('name') // 'xpulse-web'
config.get('type') // 'tool'
config.get('http.port') // '3000'
config.get('theme.default') // 'dark'
config.get('i18n.locales') // ['de', 'en']
config.get('sources.chat.url') // 'https://chat.xpulse.one'
config.get('release.current') // '1.3.0' (custom key)
// With fallback
config.get('http.port', '3000') // fallback if not set
config.get('missing.key', null) // null

Full object

config.all();
// β†’ complete object with fallbacks and resolved ${VAR} values

${ENV_VAR} Resolution

xpulse.json can reference .env values:

{
"name": "xpulse-web",
"type": "page",
"http": {
"port": "${PORT}"
},
"sources": {
"chat": {
"url": "${CHAT_URL}",
"health": "${CHAT_HEALTH_URL}"
}
}
}

config.load() resolves all ${VAR} references – after @xpulse/dotenv loading:

await config.load();
config.get('http.port') // '3000' (from .env: PORT=3000)
config.get('sources.chat.url') // 'https://chat.xpulse.one'

Unresolved variables (not in .env and not in process.env) remain as ${VAR} and produce a warning.


Fallback Values (Convention)

Key Fallback
type 'tool'
theme.default 'dark'
i18n.default 'de'
i18n.locales ['de']
paths.templates 'src/templates/'
paths.locales 'src/locales/'
paths.public 'src/public/'
http.port process.env.PORT || '3000'
sources.*.docs false
sources.*.type 'tool'

Validation

config.load() validates known standard keys:

Error Behaviour
xpulse.json not found throws Error
Invalid JSON throws Error
name missing throws Error
Unknown keys ignored, no warning
${VAR} unresolvable warning, value remains ${VAR}

Emitted Events

Event Payload When
config:loaded { name, type, env, files, packages } after successful config.load()
import event from '@xpulse/event';
event.on('config:loaded', ({ name, type, env, files, packages }) => {
// name – app name from xpulse.json
// type – 'tool' | 'component' | ...
// env – NODE_ENV
// files – loaded files [xpulse.json, .env, ...]
// packages – merged package configs ['@xpulse/doc', '@xpulse/theme', ...]
});

Debug Integration

When @xpulse/debug is installed as a devDependency, @xpulse/config automatically provides a DataCollector. @xpulse/debug discovers it via node_modules/@xpulse/config/src/datacollectors/ – no configuration needed.

"optionalDependencies": {
"@xpulse/debug": "^1.0.0"
}

The ConfigCollector (name: 'config', icon: 'πŸ”§') shows in the Web Profiler:

Object values in the summary (e.g. the debug block) are serialized as JSON. No toolbar badge.


Package Structure

@xpulse/config/
src/
index.js ← default export: config object
defaults.js ← fallback values (internal)
resolver.js ← ${VAR} resolution (internal)
validator.js ← validate standard keys (internal)
test/
config.test.js
resolver.test.js
validator.test.js
docs/
index.md
api.md
_meta.json
Dockerfile
Makefile
README.md
package.json
xpulse.json
en/spec.md 2026-03-27