app-etc-config
v1.0.0
Published
Creates a configuration API.
Downloads
13
Maintainers
Readme
Config
Creates a configuration API.
Installation
$ npm install app-etc-config
Usage
var etc = require( 'app-etc-config' );
etc( [options] )
Creates a configuration API.
var config = etc();
The constructor accepts the following options
:
- sep: default keypath separator used when getting and setting configuration values. See utils-deep-set and utils-deep-get. Default:
'.'
. - create:
boolean
indicating whether to create a keypath if it does not exist. See utils-deep-set. Default:true
. - schema: JSON schema for validating a configuration.
- formats: JSON schema custom formats (see jsen#custom-formats).
- extSchemas: hash containing external JSON schemas referenced by a main configuration
schema
(see jsen#external-schemas).
To specify options
,
var config = etc({
'sep': '|',
'create': false,
'schema': require( '/path/to/schema.json' ),
'formats': {
'only-a': /^a+$/
},
'extSchemas': {
'ref_schema1': require( '/path/to/ref_schema1.json' ),
'ref_schema2': require( '/path/to/ref_schema2.json' )
}
});
===
config.set( keypath, value[, options] )
Sets a configuration value at a specified keypath
.
var bool = config.set( 'foo.bar', 'beep' );
// returns a <boolean> indicating whether a value was set
/*
{
'foo': {
'bar': 'beep'
}
}
*/
The method accepts the following options
:
- sep: keypath separator used when setting configuration values. See utils-deep-set.
- create:
boolean
indicating whether to create a keypath if it does not exist. See utils-deep-set.
Specifying method options
will override the default options
provided during config
creation.
===
config.merge( [keypath,] config[, options] )
Merges a configuration object
or another config
instance.
var bool = config.merge({
'beep': 'boop'
});
// returns a <boolean> indicating if merge was successful
/*
{
'foo': {
'bar': 'beep'
},
'beep': 'boop'
}
*/
If provided a keypath
, the method merges a configuration object with a sub-configuration.
var config2 = etc();
config2.set( 'hello', 'world' );
var bool = config.merge( 'foo', config2 );
/*
{
'foo': {
'bar': 'beep',
'hello': 'world'
},
'beep': 'boop'
}
*/
If a keypath
does not correspond to an object
, the method returns false
and set()
should be used instead.
var bool = config.merge( 'abcdefg', config2 );
// returns false
/*
{
'foo': {
'bar': 'beep',
'hello': 'world'
},
'beep': 'boop'
}
*/
bool = config.set( 'abcdefg', config2 );
// returns true
The method accepts the following options
:
- sep: keypath separator used when merging nested configuration values. See utils-deep-set.
Specifying method options
will override the default options
provided during config
creation.
===
config.get( [ keypath[, options] ] )
Returns a copy of the raw configuration store.
var obj = config.get();
/*
{
'foo': {
'bar': 'beep',
'hello': 'world'
},
'beep': 'boop'
}
*/
If provided a keypath
, the method returns a copy of the corresponding configuration value.
var val = config.get( 'foo.hello' );
// returns 'world'
If a keypath
does not exist, the method returns undefined
.
var val = config.get( 'non.existent.path' );
// returns undefined
The method accepts the following options
:
- sep: keypath separator used when getting configuration values. See utils-deep-get.
Specifying method options
will override the default options
provided during config
creation.
===
config.clone( [keypath[, options] ] )
Clones a config
instance.
var config2 = config.clone();
console.log( config2.get() );
/*
{
'foo': {
'bar': 'beep',
'hello': 'world'
},
'beep': 'boop'
}
*/
console.log( config === config2 );
// returns false
If provided a keypath
, the method clones a sub-configuration value as a new config
instance.
var config2;
// Configuration value is an object:
config2 = config.clone( 'foo' );
/*
{
'bar': 'beep',
'hello': 'world'
}
*/
// Configuration value is not an object:
config2 = config.clone( 'beep' );
/*
{
'beep': 'boop'
}
*/
If a keypath
does not exist, the method returns undefined
.
var config3 = config.clone( 'non.existent.path' );
// returns undefined
The method accepts the following options
:
- sep: keypath separator used when getting configuration values. See utils-deep-get.
Specifying method options
will override the default options
provided during config
creation.
===
config.load( filename )
Convenience method which loads and merges a configuration file.
config.load( '/path/to/config/file.<ext>' );
Note: this method does not directly support loading a configuration file into a sub-configuration. To achieve this, use app-etc-load and then merge
at a specified keypath
.
var load = require( 'app-etc-load' );
var obj = load( '/path/to/config/file.<ext>' );
config.merge( 'foo', obj );
===
config.validate( [validator] )
Validates a configuration.
// Valid configuration:
var out = config.validate();
// returns true
If a configuration is invalid, the method returns an array
containing validation errors.
// Invalid configuration:
out = config.validate();
// returns [{...},{...},...]
The method accepts a validator
function, which can be useful for validating against multiple schemas or when a schema
was not provided during initialization. The validator
should accept as its first argument the configuration object
to be validated. The method returns validation results without modification.
// Example JSON schema validator:
var validator = require( 'jsen' );
var schema = require( '/path/to/schema.json' );
var validate = validator( schema, {
'greedy': true
});
var out = config.validate( validate );
console.log( out );
console.log( validate.errors );
If a schema
option was not provided during initialization and a validator
is not provided at runtime, the method always returns true
.
var config = etc();
config.set( 'port', 80 );
var out = config.validate();
// returns true
===
etc.exts()
Returns a list of supported filename extensions.
var exts = etc.exts();
// returns ['.json','.toml',...]
For more details, see app-etc-load.
etc.parser( extname[, parser] )
Returns a parser for the specified extension.
var parser = etc.parser( '.json' );
Including the .
when specifying an extension is optional.
var parser = etc.parser( 'json' );
To support additional file formats or to override a parser, provide a parser
function for an associated extension.
var parser = require( 'my-special-fmt-parser' );
etc.parser( '<my-ext>', parser );
Once a parser is set, all config
instances will parse provided files accordingly.
config.load( './file.<my-ext>' );
For more details, see app-etc-load.
Notes
This module uses jsen for validating an internal configuration
object
against a JSON schema. One compelling feature of jsen is the ability to extend a schema definition by specifying custom error messages. For example, given the following schema,{ "type": "object", "definitions": { "port": { "description": "schema for a port", "type": "integer", "minimum": 1024, "maximum": 65536, "requiredMessage": "port is required", "messages": { "type": "invalid type. Must be an integer.", "minimum": "invalid value. Must be an integer greater than or equal to 1024.", "maximum": "invalid value. Must be an integer less than or equal to 65536." } } }, "properties": { "port": { "$ref": "#/definitions/port" } }, "required": [ "port" ], "messages": { "type": "invalid data type where an object is expected" } }
validation will return more informative error messages based on keywords.
var validator = require( 'jsen' ); var validate = validator( schema ); var bool = validate({ 'port': 80 }) console.dir( validate.errors ); /* [ { 'path': 'port', 'keyword': 'minimum', 'message': 'invalid value. Must be an integer greater than or equal to 1024.' } ] */
Examples
var etc = require( 'app-etc-config' );
// Create a new configuration API:
var config = etc();
// Load local files:
config.load( './.travis.yml' );
console.dir( config.get() );
config.load( './package.json' );
console.dir( config.get() );
// Merge in a custom object:
config.merge( 'author', {
'beep': 'boop'
});
console.dir( config.get( 'author' ) );
// Access a shallow value:
console.log( config.get( 'license' ) );
// Access nested values:
console.log( config.get( 'author.name' ) );
// Create and set shallow values:
config.set( 'hello', false );
console.log( config.get( 'hello' ) );
// Create and set deeply nested values:
config.set( 'foo.bar.bip', 'bap', {
'create': true
});
console.log( config.get( 'foo.bar.bip' ) );
// Clone the current configuration:
var clone = config.clone();
console.log( config === clone );
// returns false
To run the example code from the top-level application directory,
$ node ./examples/index.js
Tests
Unit
Unit tests use the Mocha test framework with Chai assertions. To run the tests, execute the following command in the top-level application directory:
$ make test
All new feature development should have corresponding unit tests to validate correct functionality.
Test Coverage
This repository uses Istanbul as its code coverage tool. To generate a test coverage report, execute the following command in the top-level application directory:
$ make test-cov
Istanbul creates a ./reports/coverage
directory. To access an HTML version of the report,
$ make view-cov
License
Copyright
Copyright © 2015. Athan Reines.