UNPKG

@foal/core

Version:

Full-featured Node.js framework, with no complexity

195 lines (194 loc) 6.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Config = void 0; // 3p const fs_1 = require("fs"); const path_1 = require("path"); // FoalTS const config_not_found_error_1 = require("./config-not-found.error"); const config_type_error_1 = require("./config-type.error"); const env_1 = require("./env"); /** * Static class to access environment variables and configuration files. * * This class can also be used as a service. * * @export * @class Config */ class Config { static get(key, type, defaultValue) { const value = this.readConfigValue(key); if (value === undefined) { return defaultValue; } if (type === 'string' && typeof value !== 'string') { throw new config_type_error_1.ConfigTypeError(key, 'string', typeof value); } if (type === 'boolean' && typeof value !== 'boolean') { if (value === 'true') { return true; } if (value === 'false') { return false; } throw new config_type_error_1.ConfigTypeError(key, 'boolean', typeof value); } if (type === 'number' && typeof value !== 'number') { if (typeof value === 'string' && value.replace(/ /g, '') !== '') { const n = Number(value); if (!isNaN(n)) { return n; } } throw new config_type_error_1.ConfigTypeError(key, 'number', typeof value); } if (type === 'boolean|string' && typeof value !== 'boolean') { if (value === 'true') { return true; } if (value === 'false') { return false; } if (typeof value !== 'string') { throw new config_type_error_1.ConfigTypeError(key, 'boolean|string', typeof value); } } if (type === 'number|string' && typeof value !== 'number') { if (typeof value !== 'string') { throw new config_type_error_1.ConfigTypeError(key, 'number|string', typeof value); } if (value.replace(/ /g, '') !== '') { const n = Number(value); if (!isNaN(n)) { return n; } } } return value; } /** * Read the configuration value associated with the given key. Optionaly check its type. * * Throw an ConfigNotFoundError if no value is found. * * @static * @template T * @param {string} key - The configuration key. * @param {T} [type] - The expected type of the returned value. * @param {string} [msg] - The message of the ConfigNotFoundError if no value is found. * @returns {ValueType<T>} The configuration value. * @memberof Config */ static getOrThrow(key, type, msg) { const value = this.get(key, type); if (value === undefined) { throw new config_not_found_error_1.ConfigNotFoundError(key, msg); } return value; } /** * Clear the cache of the loaded files. * * @static * @memberof Config */ static clearCache() { this.config = null; this.testConfig.clear(); } static set(key, value) { this.testConfig.set(key, value); } static remove(key) { this.testConfig.delete(key); } static yaml; static config = null; static testConfig = new Map(); static readJSON(path) { if (!(0, fs_1.existsSync)(path)) { return {}; } const fileContent = (0, fs_1.readFileSync)(path, 'utf8'); return JSON.parse(fileContent); } static readYAML(path) { if (!(0, fs_1.existsSync)(path)) { return {}; } const yaml = this.getYAMLInstance(); if (!yaml) { console.log(`Impossible to read ${path}. The package "yamljs" is not installed.`); return {}; } const fileContent = (0, fs_1.readFileSync)(path, 'utf8'); return yaml.parse(fileContent); } static readJS(path) { if (!(0, fs_1.existsSync)(path)) { return {}; } return require((0, path_1.join)(process.cwd(), path)); } static readConfigValue(key) { if (this.testConfig.has(key)) { return this.testConfig.get(key); } if (this.config === null) { this.config = [ this.readJS('config/default.js'), this.readYAML('config/default.yml'), this.readJSON('config/default.json'), this.readJS(`config/${env_1.Env.getEnvironmentName()}.js`), this.readYAML(`config/${env_1.Env.getEnvironmentName()}.yml`), this.readJSON(`config/${env_1.Env.getEnvironmentName()}.json`), ].reduce((config1, config2) => this.mergeDeep(config1, config2)); } const properties = key.split('.'); let result = this.config; for (const property of properties) { result = result[property]; if (result === undefined) { break; } } if (typeof result === 'string' && result.startsWith('env(') && result.endsWith(')')) { const envVarName = result.substr(4, result.length - 5); return env_1.Env.get(envVarName); } return result; } static mergeDeep(target, source) { // TODO: improve the tests of this function. function isObject(o) { return typeof o === 'object' && o !== null; } for (const key in source) { if (isObject(target[key]) && isObject(source[key])) { this.mergeDeep(target[key], source[key]); } else if (source[key] !== undefined) { target[key] = source[key]; } } return target; } static getYAMLInstance() { // TODO: test this method (hard). if (this.yaml === false) { return false; } try { this.yaml = require('yamljs'); } catch (err) { if (err.code !== 'MODULE_NOT_FOUND') { throw err; } this.yaml = false; } return this.yaml; } } exports.Config = Config;