comfy
Version:
Configure your applications comfortably
161 lines (137 loc) • 3.48 kB
JavaScript
// comfy is good for your health, dummy
//
// Developed by Filipe Dobreira in Gabriele's living room couch.
;
/**
* Tiny helper defining the syntax for defining properties, and
* container for the resolved properties.
*
* @class
*/
function Comfy(env) {
this.env = env;
}
/**
* Defines a required property.
*
* @example
* this.required("github_api_key");
*
* @example
* // Same as the following:
* this.property("github_api_key", { required: true });
*
* @arg {string} name
* @arg {Object} options
*/
Comfy.prototype.required = function (name, options) {
var newOptions = this.withOptions(options);
newOptions.required = true;
this.property(name, newOptions);
};
/**
* Defines an optional property.
*
* @example
* this.optional("s3_bucket", "default_bucket_ident")
*
* @example
* // Same as the following:
* this.property
*
* @arg {string} name
* @arg defaultValue
* @arg {Object} options
*/
Comfy.prototype.optional = function (name, defaultValue, options) {
var newOptions = this.withOptions(options);
if (typeof defaultValue === "undefined") {
throw "Optional property " + name + " with no default (got undefined)";
}
newOptions.optional = true;
newOptions.defaultValue = defaultValue;
this.property(name, newOptions);
};
/**
* Defines a property. This method is the lowest level API available
* for defining configuration through comfy; for more concise options
* see other methods: required, optional
*
* @arg {string} name
* @arg {Object} options
*/
Comfy.prototype.property = function (name, options) {
var opts = this.withOptions(options);
var envName = this.nameToEnvKey(name);
var envValue = this.env[envName];
if (typeof envValue === "undefined") {
if (opts.optional) {
envValue = opts.defaultValue;
} else {
throw "Required property " + envName + " not present in env:" + this.env;
}
}
if (opts.transform) {
envValue = opts.transform.call(null, envValue);
}
if (opts.alias) {
name = opts.alias;
}
this.setProperty(name, envValue);
};
/**
* @param {string} name
* @param value
*/
Comfy.prototype.setProperty = function (name, value) {
this[name] = value;
this[this.nameToCamelCaseKey(name)] = value;
};
/**
* Transforms a snake_case property name into the correct name format
* to scan for a matching environment variable.
*
* @param {string} name
* @returns {string}
*/
Comfy.prototype.nameToEnvKey = function (name) {
return name.toUpperCase();
};
/**
* Transforms a snake_case property name into camelCase
*
* @param {string} name
* @returns {string}
*/
Comfy.prototype.nameToCamelCaseKey = function (name) {
return name.replace(/(\_\w)/g, function (m) {
return m[1].toUpperCase();
});
};
/**
* Normalizes the options object and discards anything it
* doesn't understand.
*
* @todo Complain loudly if an unknown property is provided
*
* @arg {Object} options
* @returns {Object}
*/
Comfy.prototype.withOptions = function (options) {
var opts = options || {};
return {
required: opts.required || false,
transform: opts.transform || null,
optional: opts.optional || false,
defaultValue: opts.defaultValue || undefined,
alias: opts.alias || null
};
};
module.exports = {
build: function (definition, customEnv) {
var env = customEnv || process.env;
var config = new Comfy(env);
definition.call(null, config);
return config;
}
};