UNPKG

botpress

Version:

The world's first CMS for bots. Easily create, manage and extend chatbots.

203 lines (157 loc) 8.82 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _joi = require('joi'); var _joi2 = _interopRequireDefault(_joi); var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); var _yn = require('yn'); var _yn2 = _interopRequireDefault(_yn); var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs); var _json = require('json5'); var _json2 = _interopRequireDefault(_json); var _module = require('./module'); var _module2 = _interopRequireDefault(_module); var _util = require('../util'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /** * The Configuration Manager is in charge of the configuration * for all the modules. It knows how to provision and load configuration * from the right places (env variables, files, botfile). * @namespace ConfigurationManager * @private */ const validations = { any: (value, validation) => validation(value), string: (value, validation) => typeof value === 'string' && validation(value), choice: (value, validation) => _lodash2.default.includes(validation, value), bool: (value, validation) => ((0, _yn2.default)(value) === true || (0, _yn2.default)(value) === false) && validation(value) }; const transformers = { bool: value => (0, _yn2.default)(value) }; const defaultValues = { any: null, string: '', bool: false }; const amendOption = (option, name) => { const validTypes = _lodash2.default.keys(validations); if (!option.type || !_lodash2.default.includes(validTypes, option.type)) { throw new Error(`Invalid type (${option.type || ''}) for config key (${name})`); } const validation = option.validation || (() => true); if (typeof option.default !== 'undefined' && !validations[option.type](option.default, validation)) { throw new Error(`Invalid default value (${option.default}) for (${name})`); } if (!option.default && !_lodash2.default.includes(_lodash2.default.keys(defaultValues), option.type)) { throw new Error(`Default value is mandatory for type ${option.type} (${name})`); } return { type: option.type, required: option.required || false, env: option.env || null, default: option.default || defaultValues[option.type], validation: validation }; }; const amendOptions = options => { return _lodash2.default.mapValues(options, amendOption); }; class ConfigurationManager { constructor(options) { if (_util.isDeveloping) { const schema = _joi2.default.object().keys({ configLocation: _joi2.default.string().min(1).required(), botfile: _joi2.default.object().required(), logger: _joi2.default.object().required() }); _joi2.default.assert(options, schema, 'Invalid constructor elements for Configuration Manager'); } this.configLocation = options.configLocation; this.botfile = options.botfile; this.logger = options.logger; this._memoizedLoadAll = _lodash2.default.memoize(this._loadAll.bind(this)); } _loadFromDefaultValues(options) { return _lodash2.default.mapValues(options, value => value.default); } _loadFromConfigFile(file, options) { const filePath = _path2.default.resolve(this.configLocation, file); if (_fs2.default.existsSync(filePath)) { const content = _fs2.default.readFileSync(filePath, 'utf8'); return _json2.default.parse(content); } return {}; } _loadFromEnvVariables(options) { const obj = {}; _lodash2.default.mapValues(process.env, (value, key) => { if (_lodash2.default.isNil(value)) { return; } const entry = _lodash2.default.findKey(options, { env: key }); if (entry) { obj[entry] = value; } }); return obj; } _loadAll(file, options = {}) { options = amendOptions(options); let config = this._loadFromDefaultValues(options); Object.assign(config, this._loadFromConfigFile(file, options)); Object.assign(config, this._loadFromEnvVariables(options)); // Transform the values if there's a transformer for this type of value config = _lodash2.default.mapValues(config, (value, key) => { const { type } = options[key]; if (transformers[type]) { return transformers[type](value); } else { return value; } }); return config; } /** * Returns a Configuration for a specific module * @param {Object} module A module object * @private * @return {ModuleConfiguration} A module-specific configuration */ getModuleConfiguration(module) { return new _module2.default({ manager: this, module: module, configLocation: this.configLocation, logger: this.logger }); } /** * Loads configuration from the right module * @param {String} file The name of the configuration file * @param {Object} options * @private * @return {Object} The full configuration object, assembled from various sources */ loadAll(file, options, caching = true) { var _this = this; return _asyncToGenerator(function* () { const getter = caching ? _this._memoizedLoadAll : _this._loadAll; return getter(file, options); })(); } get(file, key, options, caching = true) { var _this2 = this; return _asyncToGenerator(function* () { const config = yield _this2.loadAll(file, options, caching); return config[key]; })(); } } exports.default = ConfigurationManager; //# sourceMappingURL=index.js.map