Confab: Simple Node.js Configurations
- 9/5/2015
- ·
- #index
Node.js service configurations run the gamut from sophisticated
libraries to ad-hoc lookups of environment variables or
arbitrary JSON on the file system. Somewhere in the middle lies
confab
, a tiny utility for building configurations that are
simple, external, and utterly predictable.
$ npm install confab
The core concept is dead simple: a single configuration object is constructed, extended, and validated using a sequence of transformations. With no transformations supplied, the configuration is simply an empty object:
// config.js
module.exports = confab([]); // {}
That isn’t so useful, but confab
also ships with a few built-in
transformations that can:
- load configuration data from JSON
- merge environment variables
- specify defaults and required fields
assign
programmatic overridesfreeze
the results against futher modification.
To set a default port and allow the environment to override it, we can extend our empty configuration with a few transformations:
var config = confab([
confab.loadEnvironment({ 'PORT': 'port' }),
confab.defaults({ port: 3000 }),
confab.freeze()
]); // { "port": 3000 }
Custom Transformations
We can also easily define new tranformations; if we want all applications to report certain configuration values at startup, for instance, we can whitelist and log the interesting parts:
function logConfigValue (whiteList) {
return function (config) {
var output = {};
whitelist.forEach(function (key) {
if (config.hasOwnProperty(key)) {
output[key] = config[key];
}
});
console.log(output);
};
}
The custom transformation can now be used just like the built-ins:
var config = confab([
confab.loadEnvironment({ 'PORT': 'port' }),
confab.defaults({ port: 3000 }),
confab.freeze()
logConfigValue('port') // log { "port": "3000" }
]);
Portability
Besides encouraging simple, declarative configuration, confab
also provides a
platform for applying consistent rules across multiple projects. Once our
transformation list is settled, we can package the configuration logic up and
publish it to a (private) package repository. Maybe we want to require all
projects to respect JSON config files stored in a “global” directory:
module.exports = function myConfig (projectName) {
var env = process.env('NODE_ENV') || 'default';
var homeDir = process.env('USERPROFILE') || process.env('HOME');
return confab([
confab.loadJSON([
path.resolve(__dirname, 'config.json'),
path.resolve(homeDir, '.org-config', projectName + '.' + env + '.json'
]),
confab.loadEnvironment({ 'PORT': 'port' }),
confab.defaults({ port: 3000 }),
confab.freeze(),
logConfigValue(['port'])
]);
};
To reuse this configuration, we can simply install it:
$ npm install my-config
…and pass it project-specific options as needed.
// app-config.js
module.exports = require('my-config')('my-app');
Conclusion
That’s about it: simple, reusable configuration logic. It’s been invaluable to me for simplifying configuration management and runtime visibility across projects, scheduled tasks, and services, and now it’s open-sourced for your development convenience.
Happy Hacking!