181 lines
3.7 KiB
JavaScript
181 lines
3.7 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
const container = require('../Container');
|
||
|
const path = container.get('path');
|
||
|
|
||
|
// Load environment file
|
||
|
require('dotenv').config({
|
||
|
path: path.resolve(__dirname, '../../.env'),
|
||
|
});
|
||
|
|
||
|
const fs = require('fs');
|
||
|
|
||
|
const glob = require('glob');
|
||
|
const configSslPath = path.resolve(__dirname, '../config/ssl');
|
||
|
const configPath = path.resolve(__dirname, '../config');
|
||
|
|
||
|
const defaultConfig = new Map([
|
||
|
['host', 'localhost'],
|
||
|
['http', true],
|
||
|
['http-port', 80],
|
||
|
['https', false],
|
||
|
['https-port', 443],
|
||
|
['node-env', 'development'],
|
||
|
]);
|
||
|
|
||
|
const configFiles = glob.sync(`${configPath}/**/*.js`);
|
||
|
|
||
|
/**
|
||
|
* Config management class
|
||
|
*
|
||
|
* Hierarchy of config options
|
||
|
* 1. Directly defined config options
|
||
|
* 2. Environment variables
|
||
|
* 3. Default values
|
||
|
*/
|
||
|
class Config {
|
||
|
constructor() {
|
||
|
let _configMap = new Map();
|
||
|
|
||
|
// Load files in config folder under their
|
||
|
// own respective namespaces
|
||
|
configFiles.forEach((fullPath) => {
|
||
|
let key = path.basename(fullPath, '.js');
|
||
|
_configMap.set(key, require(fullPath));
|
||
|
});
|
||
|
|
||
|
this._config = _configMap;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the list of available configuration keys
|
||
|
*
|
||
|
* @return {array} - the list of configuration keys
|
||
|
*/
|
||
|
keys() {
|
||
|
let keys = [];
|
||
|
|
||
|
for (let key of this._config.keys()) {
|
||
|
keys.push(key);
|
||
|
}
|
||
|
|
||
|
return keys;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Determine if a config value exists
|
||
|
*
|
||
|
* @param {string|symbol} key - the config value key
|
||
|
* @return {boolean} - whether the config value exists
|
||
|
*/
|
||
|
has(key) {
|
||
|
return this._config.has(key);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Determine whether an environment variable is currently defined
|
||
|
*
|
||
|
* @param {string} key - the environment varaible to look for
|
||
|
* @return {boolean} - whether the environment variable is defined
|
||
|
*/
|
||
|
hasEnv(key) {
|
||
|
return process.env[this._envName(key)] != null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieve a config value
|
||
|
*
|
||
|
* @param {string|symbol} key - the name of the config value
|
||
|
* @return {*} - the configuration value
|
||
|
*/
|
||
|
get(key) {
|
||
|
if (! this.has(key)) {
|
||
|
// Fallback to environment variables
|
||
|
let envKey = key.toUpperCase().replace('-', '_');
|
||
|
if (this.hasEnv(envKey)) {
|
||
|
let envValue = this.getEnv(envKey);
|
||
|
this._config.set(key, envValue);
|
||
|
return envValue;
|
||
|
}
|
||
|
|
||
|
// Fallback to default values
|
||
|
if (defaultConfig.has(key)) {
|
||
|
let defaultValue = defaultConfig.get(key);
|
||
|
this._config.set(key, defaultValue);
|
||
|
return defaultValue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return this._config.get(key);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the value of an environment variable
|
||
|
*
|
||
|
* @param {string} key - the environment variable to get
|
||
|
* @return {string|undefined} - the value of the environment variable
|
||
|
*/
|
||
|
getEnv(key) {
|
||
|
let raw = process.env[this._envName(key)];
|
||
|
return this._normalizeValue(raw);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get equivalent environment variable for config key
|
||
|
*
|
||
|
* @private
|
||
|
* @param {string} key - the config key
|
||
|
* @return {string} - the environment variable name
|
||
|
*/
|
||
|
_envName(key) {
|
||
|
return key.toUpperCase().replace('-', '_');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Attempt to parse javascript types from strings
|
||
|
*
|
||
|
* @private
|
||
|
* @param {string} val - the string value
|
||
|
* @return {string|number|boolean} - the 'parsed' value
|
||
|
*/
|
||
|
_normalizeValue(val) {
|
||
|
let bool = /^true|false$/;
|
||
|
let integer = /^([0-9]+)$/;
|
||
|
|
||
|
if (String(val).search(integer) !== -1) {
|
||
|
return parseInt(val, 10);
|
||
|
}
|
||
|
|
||
|
if (String(val).search(bool) !== -1) {
|
||
|
switch (val) {
|
||
|
case 'true':
|
||
|
return true;
|
||
|
|
||
|
// return overrides break
|
||
|
|
||
|
case 'false':
|
||
|
return false;
|
||
|
|
||
|
// return overrides break
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return val;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set a config variable (mainly for testing)
|
||
|
*
|
||
|
* @private
|
||
|
* @param {mixed} key - the key to set
|
||
|
* @param {mixed} val - the value for the key
|
||
|
* @return {Config} - the config instance
|
||
|
*/
|
||
|
_set(key, val) {
|
||
|
this._config.set(key, val);
|
||
|
return this;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
module.exports = new Config();
|