Skip to content

Commit

Permalink
feat: Add main file with TwConf class
Browse files Browse the repository at this point in the history
  • Loading branch information
CheerlessCloud committed May 30, 2017
1 parent 1155eff commit 896f0b2
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 0 deletions.
118 changes: 118 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import * as Types from './types';
import ConfigField from './config-field';
import envParser from './env-parser';

class TwConf {
static Types = Types;

/**
* @type {Map.<string, *>}
*/
config = new Map();

/**
* @type {Map.<string, string>}
*/
env = new Map();

/**
* @method get
* @public
* @param {string} key
* @return {*}
*/
get(key) {
return this.config.get(key);
}

get flatObject() {
const result = {};

this.config.forEach((value, key) => {
result[key.replace(/([._-])([a-z\d])/g, str => str[1].toUpperCase())] = value;
});

return Object.freeze(result);
}

toString() {
return JSON.stringify(this.config);
}

/**
* Create TwConf object
* @param {(Map.<string, ConfigField>|Array.<string, ConfigField>[]|object)} confSkeleton
* @param {object=} options
* @param {boolean} [options.allowUnspecified=true]
* @param {boolean} [options.flatOnly=false]
* @param {boolean} [options.validationOnDemand=false]
*/
constructor(confSkeleton, options = {
allowUnspecified: true,
flatOnly: false,
validationOnDemand: false,
}) {
this.options = options;

/**
* @type {Map.<string, ConfigField>}
*/
this.skeleton = null;

if (confSkeleton instanceof Map) {
this.skeleton = confSkeleton;
}

if (confSkeleton instanceof Array) {
this.skeleton = new Map(confSkeleton);
}

if (typeof confSkeleton === 'object') {
this.skeleton = new Map(Object.keys(confSkeleton).map(key => [key, confSkeleton[key]]));
}

this.skeleton.forEach((value, key) => {
if (!(value instanceof ConfigField)) {
if (typeof value !== 'object') {
const err = new TypeError('Value of ConfigRule must be a object');
err.field = key;
throw err;
}

this.skeleton.set(key, new ConfigField(value));
}
});

if (!this.options.validationOnDemand) {
this.validate();
}
}

/**
* @method validate
* @public
*/
validate() {
this.env = envParser(this.options);

const errors = [];

this.skeleton.forEach((configField, key) => {
try {
this.config.set(key, configField.validate(this.env.get(key)));
} catch (err) {
err.field = key;
errors.push(err);
}
});

if (errors.length) {
const newError = new Error('Validation error');
newError.errors = errors;
throw newError;
}
}
}

export default TwConf;
module.exports = TwConf;
39 changes: 39 additions & 0 deletions src/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* eslint-env mocha */
/* globals describe, it, before, after, beforeEach, afterEach */

import { expect } from 'chai';
import TwConf from './index';
import { StringType } from './types';

describe('twconfig main tests', () => {
beforeEach(() => {
process.env = {
'DATABASE.MONGODB.HOSTNAME': 'localhost',
'DATABASE.MONGODB.PORT': '27316',
'REDIS:HASH-ALGO': 'testName',
};
});

it('simple smoke test', () => {
expect(() => {
// eslint-disable-next-line no-new
const conf = new TwConf({
'database.mongodb.hostname': {
comment: 'hostname of mongodb',
simple: 'ams3.digitalocean.com',
type: new StringType(),
// required: true,
preTransforms: [
value => String(value),
],
validators: [
value => value !== 'mongodb',
],
default: 'localhost',
},
});

expect(conf.get('database.mongodb.hostname')).to.be.equal('localhost');
}).not.to.throw();
});
});

0 comments on commit 896f0b2

Please sign in to comment.