@ultra-lean-code/yamjam
v1.0.0
Published
Composable YAML configuration loader for @ultra-lean-code/yam - load and compose YAML files with inheritance
Maintainers
Readme
YamJam - Composable YAML Configuration Loader
Load YAML configuration files with inheritance and composition. Built on @ultra-lean-code/yam, YamJam lets you compose configurations from multiple files using an extends keyword, supporting file references, same-file property inheritance, and JSON path selection with $ delimiter.
Installation
npm install @ultra-lean-code/yamjamUsage
Basic File Loading
import YamJam from '@ultra-lean-code/yamjam';
const config = await YamJam.load('./config.yaml');
console.log(config);File Inheritance
base.yaml:
database:
host: localhost
port: 5432
timeout: 30
features:
auth: true
cache: falseprod.yaml:
extends: base
database:
host: prod-db.example.com
port: 5433
features:
cache: trueResult when loading prod.yaml (extension is optional, base resolves to base.yaml):
{
database: {
host: 'prod-db.example.com',
port: 5433,
timeout: 30
},
features: {
auth: true,
cache: true
}
}Nested Property Selection
Inherit from a specific nested property in another file using $ as the path delimiter:
common.yaml:
environments:
development:
debug: true
port: 3000
production:
debug: false
port: 8080my-config.yaml:
extends: common.yaml$environments.production
app:
name: MyAppResult:
{
debug: false,
port: 8080,
app: {
name: 'MyApp'
}
}Property-Level Composition
Any property at any depth can inherit from external files:
db-configs.yaml:
postgres:
host: localhost
port: 5432
ssl: false
redis:
host: localhost
port: 6379app-config.yaml:
app:
name: MyApp
database:
extends: db-configs.yaml$postgres
host: prod.example.com
ssl: true
cache:
extends: db-configs.yaml$redis
host: cache.example.comResult:
{
app: {
name: 'MyApp'
},
database: {
host: 'prod.example.com', // overridden
port: 5432, // inherited
ssl: true // overridden
},
cache: {
host: 'cache.example.com', // overridden
port: 6379 // inherited
}
}Internal References
Use $ without a filename to inherit from another property in the same file:
config.yaml:
defaults:
timeout: 30
retries: 3
debug: false
development:
extends: $defaults
debug: true
production:
extends: $defaults
timeout: 60Result:
{
defaults: {
timeout: 30,
retries: 3,
debug: false
},
development: {
timeout: 30, // inherited
retries: 3, // inherited
debug: true // overridden
},
production: {
timeout: 60, // overridden
retries: 3, // inherited
debug: false // inherited
}
}Path and Extension Rules
Optional file extensions - uses the current file's extension:
# In config.yaml:
extends: base # Looks for base.yaml
# In config.yml:
extends: base # Looks for base.yml
# Explicit extension always works:
extends: base.yaml # Looks for base.yamlRelative paths - resolved relative to the extending file:
# In /project/config/app.yaml:
extends: ../shared/base # /project/shared/base.yaml
extends: ./local # /project/config/local.yamlAbsolute paths - start with /:
extends: /etc/myapp/base # /etc/myapp/base.yamlCombined with nested property selection:
extends: ../shared/db$postgres # /project/shared/db.yaml, postgres property
extends: /etc/app/config$database # /etc/app/config.yaml, database propertyFeatures
- File Loading: Load YAML files from the filesystem
- File-Level Inheritance: Use
extends: filepathat the root to inherit configuration - Property-Level Inheritance: Use
extends: filepathon any property at any depth - Internal References: Use
extends: $path.to.propertyto inherit from the same file - Nested Property Selection: Use
extends: filepath$path.to.propertyto inherit specific nested properties - Optional File Extensions: File extensions are optional (uses current file's extension, e.g.,
.yaml,.yml) - Relative Paths: File paths resolved relative to the extending file (unless absolute)
- Absolute Paths: Paths starting with
/are treated as absolute - Configurable Keyword: Customize the extends property name (default:
"extends") - Deep Merging: Objects are merged recursively, arrays and primitives are replaced
- Circular Dependency Detection: Prevents infinite loops in extends chains
API
YamJam.load(filePath, options) (async)
Loads and parses a YAML file, resolving all inheritance and composition.
Parameters:
filePath(string): Path to the YAML file (absolute or relative to CWD)options(object): Optional configurationextendsKeyword(string): Property name to use for extends (default:"extends")
Returns: Promise - Parsed JavaScript object
Throws: Error if file not found, circular dependency detected, or invalid YAML
Example with custom keyword:
const config = await YamJam.load('./config.yaml', { extendsKeyword: 'inherits' });Merge Behavior
- Objects: Deep merged (nested properties combined)
- Arrays: Replaced (child array completely replaces parent array)
- Primitives: Replaced (child value overrides parent value)
Examples
See the tests/ directory for more examples.
License
MIT
