@axway/api-builder-runtime
Version:
API Builder Runtime
105 lines (92 loc) • 3.09 kB
JavaScript
const fs = require('fs');
const path = require('path');
const _ = require('lodash');
const requireUncached = require('require-uncached');
const envRegex = /^(.*\.)?(default|local)\.js$/;
const envLoader = require('dotenv');
/**
* Loads up the configuration files in to the global $config object.
*/
function Loader(logger, options = {}) {
let { dirname } = options;
const { defaultConfig, configOverrides } = options;
const configFiles = [];
// dirname is the configuration directory path
dirname = dirname && fs.existsSync(dirname)
&& path.basename(dirname) === 'conf' ? dirname
: path.join(dirname || process.cwd(), 'conf');
// Loads environment variables described in .env if the file exists
const envFilePath = path.join(dirname, '.env');
if (fs.existsSync(envFilePath)) {
envLoader.config({ path: envFilePath });
}
// merge in defaultConfig
let config = { dir: path.dirname(dirname) };
if (defaultConfig && _.isObject(defaultConfig)) {
config = _.merge(defaultConfig, config);
}
// Process all the other config files found
fs.existsSync(dirname) && fs.readdirSync(dirname)
.filter(n => /\.js$/.test(n))
.forEach(fn => {
// only local and default config files allowed
if (envRegex.test(fn) && !fn.startsWith('.')) {
const file = path.join(dirname, fn);
configFiles.push(file);
} else {
const confStr = `conf${path.sep}`;
logger.warn(`skipping ${confStr}${fn}. Use ${confStr}local.js or ${confStr}default.js`);
}
});
const orderedConfigs = sortConfig(configFiles);
if (orderedConfigs.length === 0) {
logger.debug('no configuration files loaded');
} else {
logger.debug(`configuration applied in this order: ${orderedConfigs}`);
}
// now merge them in the right order
orderedConfigs.forEach(file => {
mix(config, requireUncached(file));
});
if (configOverrides) {
mix(config, configOverrides);
}
return config;
}
const sortConfig = (configs) => {
const configsMap = {};
configs.forEach(fn => {
const name = path.basename(fn);
const match = envRegex.exec(name);
if (match) {
const envName = match[2];
configsMap[envName] = (configsMap[envName] || []).concat(fn);
}
});
// Sort both default and local groups
configsMap.default && configsMap.default.sort();
configsMap.local && configsMap.local.sort();
// now combine the config file lists, local will override any defaults
const ordered = (configsMap.default || [])
.concat(configsMap.local || []);
return ordered;
};
/**
* Combines the src object into the dest object
* AH: not sure why we are using _.merge and this in the same file. We should
* look to remove this and replace it with _.merge.
* @param {Object} dest - The destination object getting updated
* @param {Object} src - The object to pull properties from
*/
const mix = (dest, src) => {
Object.keys(src).forEach(function (p) {
if (dest.hasOwnProperty(p)
&& Object.prototype.toString.call(dest[p]) === '[object Object]') {
mix(dest[p], src[p]);
} else {
dest[p] = src[p];
}
});
};
Loader.sortConfig = sortConfig;
module.exports = Loader;