description and source-codefunction convict(def) {
function walk(obj, path) {
if (path) {
let ar = path.split('.');
while (ar.length) {
let k = ar.shift();
if (k in obj) {
obj = obj[k];
} else {
throw new Error("cannot find configuration param '" + path + "'");
}
}
}
return obj;
}
// TODO: Rename this `rv` variable (supposedly "return value") into something
// more meaningful.
let rv = {
getProperties: function() {
return cloneDeep(this._instance);
},
/**
* Exports all the properties (that is the keys and their current values) as
* a JSON string
*/
toString: function() {
return JSON.stringify(this._instance, null, 2);
},
/**
* Exports the schema as JSON.
*/
getSchema: function() {
return JSON.parse(JSON.stringify(this._schema));
},
/**
* Exports the schema as a JSON string
*/
getSchemaString: function() {
return JSON.stringify(this._schema, null, 2);
},
/**
* @returns the current value of the name property. name can use dot
* notation to reference nested values
*/
get: function(path) {
let o = walk(this._instance, path);
return typeof o !== 'undefined' ?
cloneDeep(o) :
void 0;
},
/**
* @returns the default value of the name property. name can use dot
* notation to reference nested values
*/
default: function(path) {
// The default value for FOO.BAR.BAZ is stored in `_schema.properties` at:
// FOO.properties.BAR.properties.BAZ.default
path = (path.split('.').join('.properties.')) + '.default';
let o = walk(this._schema.properties, path);
return typeof o !== 'undefined' ?
cloneDeep(o) :
void 0;
},
/**
* Resets a property to its default value as defined in the schema
*/
reset: function(prop_name) {
this.set(prop_name, this.default(prop_name));
},
/**
* @returns true if the property name is defined, or false otherwise
*/
has: function(path) {
try {
let r = this.get(path);
// values that are set but undefined return false
return typeof r !== 'undefined';
} catch (e) {
return false;
}
},
/**
* Sets the value of name to value. name can use dot notation to reference
* nested values, e.g. "database.port". If objects in the chain don't yet
* exist, they will be initialized to empty objects
*/
set: function(k, v) {
v = coerce(k, v, this._schema, this);
let ar = k.split('.');
let o = this._instance;
while (ar.length > 1) {
k = ar.shift();
if (!o[k]) o[k] = {};
o = o[k];
}
o[ar.shift()] = v;
return this;
},
/**
* Loads and merges a JavaScript object into config
*/
load: function(conf) {
overlay(conf, this._instance, this._schema);
// environment and arguments always overrides config files
importEnvironment(rv);
importArguments(rv);
return this;
},
/**
* Loads and merges one or multiple JSON configuration files into config
*/
loadFile: function(paths) {
let self = this;
if (!Array.isArray(paths)) paths = [paths];
paths.forEach(function(path) {
overlay(loadJSON(path), self._instance, self._schema);
});
// environment and arguments always overrides config files
importEnvironment(rv);
importArguments(rv);
return this;
},
/**
* Validates config against the schema used to initialize it
*/
validate: function(options) {
options = options || {};
if ('strict' in options) {
if(options.strict){
options.allowed = ALLOWED_OPTION_STRICT
deprecate('this syntax is outdated: validate({strict: true}), you must use: validate({allowed: \'' + ALLOWED_OPTION_STRI ...