UNPKG

@kitmi/config

Version:

JavaScript env-aware config system

233 lines (232 loc) 8.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: all[name] }); } _export(exports, { EnvAwareJsonConfigProvider: function() { return EnvAwareJsonConfigProvider; }, EnvAwareYamlConfigProvider: function() { return EnvAwareYamlConfigProvider; }, default: function() { return _default; } }); const _utils = require("@kitmi/utils"); const _JsonConfigProvider = /*#__PURE__*/ _interop_require_default(require("./JsonConfigProvider.js")); const _YamlConfigProvider = /*#__PURE__*/ _interop_require_default(require("./YamlConfigProvider.js")); const _EnvAwareConfigProviderF = /*#__PURE__*/ _interop_require_default(require("./EnvAwareConfigProviderF.js")); const _defaultSyntax = /*#__PURE__*/ _interop_require_wildcard(require("./defaultSyntax.js")); function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interop_require_wildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = { __proto__: null }; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for(var key in obj){ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } const EnvAwareJsonConfigProvider = (0, _EnvAwareConfigProviderF.default)('.json', _JsonConfigProvider.default); const EnvAwareYamlConfigProvider = (0, _EnvAwareConfigProviderF.default)('.yaml', _YamlConfigProvider.default); class ConfigLoader { /** * Create an environment aware JSON config loader * @param {string} configDir * @param {string} baseName * @param {string} envFlag * @param {Logger} logger * @param {function} overrider * @param {object} postProcessors */ static createEnvAwareJsonLoader(configDir, baseName, envFlag, logger, overrider, postProcessors) { return new ConfigLoader(new EnvAwareJsonConfigProvider(configDir, baseName, envFlag, overrider), logger, postProcessors); } /** * Create an environment aware YAML config loader * @param {string} configDir * @param {string} baseName * @param {string} envFlag * @param {Logger} logger * @param {function} overrider * @param {object} postProcessors */ static createEnvAwareYamlLoader(configDir, baseName, envFlag, logger, overrider, postProcessors) { return new ConfigLoader(new EnvAwareYamlConfigProvider(configDir, baseName, envFlag, overrider), logger, postProcessors); } /** * Start loading the config files and override existing * @param {object} variables - variables * @returns {Promise.<object>} */ async load_(variables) { const oldData = this.data; await this.reload_(variables); if (oldData) { this.data = _utils._.defaults(this.data, oldData); } return this.data; } /** * Reload config * @returns {Promise.<object>} */ async reload_(variables) { this.data = await this.provider.load_(this.logger, true); if (this.autoPostProcess) this.postProcess(variables); return this.data; } /** * PostProcess the loaded config * @param {object} variables - variables */ postProcess(variables) { const queue = [ this.data ]; this._l = this.postProcessors.prefix.length; variables = { ...variables, $this: this.data }; const interpolateElement = (coll, key, val)=>{ // Process the value if (typeof val === 'string') { coll[key] = this._tryProcessStringValue(val, variables); } else if (_utils._.isPlainObject(val) || _utils._.isArray(val)) { queue.push(val); } // Process the key if it's wrapped in brackets if (typeof key === 'string' && key.startsWith('[') && key.endsWith(']')) { const keyContent = key.substring(1, key.length - 1); const processedKey = this._tryProcessStringValue(keyContent, variables); if (key !== `[${processedKey}]`) { // Create new entry with processed key and delete the old one coll[processedKey] = coll[key]; delete coll[key]; } } }; let offset = 0; while(queue.length > offset){ const node = queue[offset]; if (_utils._.isPlainObject(node)) { _utils._.forOwn(node, (value, key)=>{ interpolateElement(node, key, value); }); } else { const l = node.length; for(let i = 0; i < l; i++){ interpolateElement(node, i, node[i]); } } offset++; } } _tryProcessStringValue(strVal, variables) { if (strVal.startsWith(this.postProcessors.prefix)) { const colonPos = strVal.indexOf(':'); if (colonPos > this._l) { const token = strVal.substring(this._l, colonPos); const operator = this.postProcessors.processors[token]; if (operator) { return operator(strVal.substring(colonPos + 1), variables); } throw new Error('Unsupported post processor: ' + token); } throw new Error('Invalid post processor syntax: ' + strVal); } else if (strVal.startsWith('${') && strVal.endsWith('}')) { const operator = this.postProcessors.processors[_defaultSyntax.ES6_TEMPLATE_TOKEN]; return operator(strVal, variables); } return strVal; } /** * The config loader * @constructs ConfigLoader * @extends EventEmitter * @example * let fileSource = new JsonConfigProvider('path/to/config.json'); * let config = new ConfigLoader(fileSource); * await config.load_()...; * * let dbSource = new DbConfigProvider(config.data.dbConnection); * config.provider = dbSource; * await config.reload_()...; * * // same as: let envAwareLoader = new ConfigLoader( * // new (EnvAwareConfigProviderF('.json', JsonConfigProvider, 'default'))('config/dir', 'app', 'production') * // ); * let envAwareLoader = ConfigLoader.createEnvAwareJsonLoader('config/dir', 'app', 'production'); * * // Loader will load config/dir/app.default.json first, * // and then load config/dir/app.production.json, * // and finally override the default. * let cfg = await envAwareLoader.load_(); */ constructor(configProvider, logger, postProcessors){ /** * The config data source provider * @type {object} * @public **/ this.provider = configProvider; /** * The config data * @type {object} * @public **/ this.data = undefined; /** * Whether to do string post process automatically after loading * @type {boolean} * @public */ this.autoPostProcess = true; /** * Logger with log(level, message, meta) function. * @type {Logger} * @public */ this.logger = logger; /** * Post processors * @private */ this.postProcessors = postProcessors != null ? _utils._.defaultsDeep(postProcessors, _defaultSyntax.default) : _defaultSyntax.default; } } const _default = ConfigLoader; //# sourceMappingURL=ConfigLoader.js.map