Skip to content

Commit

Permalink
ES6 flavour
Browse files Browse the repository at this point in the history
  • Loading branch information
shidhincr committed Jun 23, 2016
1 parent fa253ab commit 8dd7b6d
Show file tree
Hide file tree
Showing 10 changed files with 262 additions and 265 deletions.
5 changes: 5 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"moduleId": "Reconfig",
"presets": ["es2015","stage-0"],
"plugins": ["add-module-exports", "transform-es2015-modules-umd"]
}
13 changes: 13 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"parser": "babel-eslint",
"ecmaFeatures": {
"jsx": true,
"modules": true
},
"env": {
"es6": true
},
"plugins": [
"react"
]
}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*.log
/node_modules
/node_modules
.idea
2 changes: 2 additions & 0 deletions build/reconfig.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions build/reconfig.min.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 13 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
"name": "reconfig",
"version": "2.1.0",
"description": "JavaScript configurations as they're meant to be. Kinda.",
"main": "reconfig.js",
"main": "build/reconfig.js",
"scripts": {
"test": "RECONFIG_envKey=value RECONFIG_confKey=newValue RECONFIG_list_1_key=newValue mocha -b"
"test": "npm run build && RECONFIG_envKey=value RECONFIG_confKey=newValue RECONFIG_list_1_key=newValue mocha -b",
"compile": "babel reconfig.es6.js -o build/reconfig.js",
"build": "npm run compile && uglifyjs build/reconfig.js -o build/reconfig.js --source-map build/reconfig.min.js.map",
"prepublish": "npm test"
},
"repository": {
"type": "git",
Expand All @@ -22,7 +25,14 @@
},
"homepage": "https://github.com/namshi/reconfig",
"devDependencies": {
"mocha": "*"
"babel-cli": "^6.10.1",
"babel-eslint": "^6.1.0",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-plugin-transform-es2015-modules-umd": "^6.8.0",
"babel-preset-es2015": "^6.9.0",
"babel-preset-stage-0": "^6.5.0",
"mocha": "*",
"uglify-js": "^2.6.4"
},
"dependencies": {
"lodash": "4.5.1",
Expand Down
197 changes: 197 additions & 0 deletions reconfig.es6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
'use strict';
import _ from 'lodash';
import vpo from 'vpo';

let getConfigFromEnv = (prefix, separator = '_') => {
let envConfig = {};

_.forEach(process.env, (value, key) => {
if (_.includes(key, prefix)) {
let path = key.replace(prefix + separator, '').replace(new RegExp(separator, 'g'), '.');
vpo.set(envConfig, path, value);
}
});

return envConfig;
}

export default class Reconfig {
_config = null;
_rawConfig = null;

/**
* Constructor
* @param config {object}
* @param envPrefix
* @param separator
*/
constructor(config, envPrefix, separator) {
this._envPrefix = envPrefix;
this._separator = separator;
this.set(config);
}

/**
* Replaces overlays in a value of the config.
* Overlays are usually references to other config
* values such as:
*
* helloworld: '{{ hello }} world!'
*
* so what this function does is basically
* resolving the value in the overlay.
*
* @param {string} value
* @param {Config} config
* @return {string}
*/
resolveReferences(value = '') {
let reference = null;
let references = value.match(/{{\s*[\w\.]+\s*}}/g);

if (references && references.length === 1) {
reference = this.resolve(this.get(references[0].replace(/[^\w.]/g, '')));

if (typeof reference === 'object') {
return reference;
}
}

return value.replace(/{{\s*[\w\.]+\s*}}/g, ref => {
return this.resolve(this.get(ref.replace(/[^\w.]/g, '')));
});
}

/*
* Resolves all the parameters of the Config's
* value.
*
* A parameter is a string preceded by a colon,
* for example:
*
* 'This is my config :value'
*
* This function will be responsible of iterating
* through the parameters provided and trying to
* replace them in the value. If a parameter is
* not found, it will be ignored.
*
* @param value
* @param parameters
* @return {*}
*/
resolveParameters(value, parameters) {
for (let property in parameters) {
if (value) {
value = value.replace(RegExp(':' + property, 'g'), (parameters[property] || ''));
}
}

return value;
}

/**
* Resolves overlays in a required object
*
* @param object
* @param parameters
* @returns {*}
*/
resolveObject(object, parameters) {
let clonedObject = _.cloneDeep(object);

_.forEach(clonedObject, (value, key) => {
clonedObject[key] = this.resolve(value, parameters);
});

return clonedObject;
}

/**
* Resolve the obtained value,
* if value is an object it will recursively resolve the overlays
*
* @param value
* @param parameters
* @returns {*}
*/
resolve(value, parameters) {
if (typeof value === 'string') {
value = this.resolveReferences(value);

if (parameters) {
value = this.resolveParameters(value, parameters);
}
}

if (typeof value === 'object') {
value = this.resolveObject(value, parameters);
}

return value;
}

set(config) {
if (!config) {
return;
}

if (this._envPrefix) {
if (process && process.env && typeof process.env !== 'string') {
_.merge(config, getConfigFromEnv(this._envPrefix, this._separator));
} else {
console.warn('HEY HEY HEY, this feature is supposed to be used in node only :)');
}
}

this._config = this._rawConfig = (_.isObject(this._rawConfig) || _.isArray(this._rawConfig)) ? _.merge(this._rawConfig, config) : config;
this._config = this.resolve(this._config);
}

/**
* Returns a configuration value, by path.
*
* If the configuration contains an object
* 'greet' with a property 'formal' of value
* 'Hello sir.', you can access it with a
* convenient dot notation.
*
* Config.get('greet.formal') // Hello sir.
*
* Values can reference other values, for
* example:
*
* greet: {
* base: 'Hello',
* formal: '{{ greet.base }} sir.'
* }
*
* Values can also contain parameters:
*
* greet: {
* base: 'Hello',
* formal: '{{ greet.base }} :name.'
* }
*
* which can then be resolved with:
*
* Config.get('greet.formal', {name: 'John'})
*
* which will return "Hello John".
*
* @param {String} path
* @param {Object} parameters
* @param {*} fallbackValue
* @return {*}
*/
get(path, parameters, fallbackValue) {
if (!path) {
return this._config;
}

let value = vpo.get(this._config, path, fallbackValue);
value = (parameters) ? this.resolve(value, parameters) : value;

return (_.isUndefined(value) || _.isNull(value)) ? null : value;
}
}
Loading

0 comments on commit 8dd7b6d

Please sign in to comment.