UNPKG

@roit/roit-environment

Version:

Facilitate environment management in node applications

211 lines (210 loc) 7.45 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Environment = void 0; const dotRef = require("dot-object"); const chalk_1 = require("chalk"); const Env_1 = require("./Env"); const fs = require("fs"); const YAML = require("yamljs"); class Environment { constructor() { this.envEnum = Env_1.Env.DEV; this.loadEnvironment(); } static envOptions(options) { this.instance.option = options; this.instance.loadEnvironment(); } static getInstance() { return this.instance; } static addProperty(key, value, setInEnv = true) { if (setInEnv) { const currentEnvVars = this.getInstance().env[this.getInstance().envEnum]; this.getInstance().env[this.getInstance().envEnum] = this.createDotNotationObject(currentEnvVars, key, value); } this.getInstance().env = this.createDotNotationObject(this.getInstance().env, key, value); this.getInstance().loadEnvVariables(); } static createDotNotationObject(objectRef, key, value) { const object = objectRef || {}; if (!key.includes(".")) { object[key] = value; return object; } return dotRef.str(key, value, object); } static getEnvValue(key) { const envValue = this.getValueFromCurrentEnv(key); if (envValue) return envValue; return this.getValueFromGlobalEnv(key); } static getValueFromCurrentEnv(key) { try { return dotRef.pick(key, this.getInstance().env[this.getInstance().envEnum]); } catch (_a) { return null; } } static getValueFromGlobalEnv(key) { try { return dotRef.pick(key, this.getInstance().env); } catch (_a) { return null; } } static acceptedEnv(...environments) { return environments.includes(this.getInstance().envEnum); } static currentEnv() { return this.getInstance().envEnum; } loadEnvironment() { this.setEnvironmentType(); this.loadYamlFile(); this.handlePropertyOverride(); } setEnvironmentType() { var _a, _b; if ((_a = this.option) === null || _a === void 0 ? void 0 : _a.manuallyEnv) { this.envEnum = this.option.manuallyEnv; return; } const envKey = ((_b = this.option) === null || _b === void 0 ? void 0 : _b.keyPropertyEnv) || 'ENV'; this.envEnum = process.env[envKey] || Env_1.Env.DEV; console.log(chalk_1.default.green(`Environment ${chalk_1.default.magentaBright(this.envEnum)} selected!`)); } loadYamlFile() { var _a; const yamlFileName = ((_a = this.option) === null || _a === void 0 ? void 0 : _a.fileYamlName) || 'env.yaml'; try { this.env = YAML.parse(fs.readFileSync(yamlFileName).toString()); this.loadEnvVariables(); } catch (error) { this.handleYamlError(error, yamlFileName); } } handleYamlError(error, fileName) { if (error.name === "YAMLException") { console.log(chalk_1.default.red(`Error in load file yaml (${fileName})`)); console.log(chalk_1.default.red(`Reason ${error.reason}`)); console.log(chalk_1.default.red(`Message: ${error.message}`)); return; } if (error.code === 'ENOENT') { console.log(chalk_1.default.red(`File (${fileName}) not found error`)); console.log(chalk_1.default.red(`Path ${error.path}`)); return; } console.log(chalk_1.default.red(`Error in load file yaml`)); console.log(chalk_1.default.red(error)); } handlePropertyOverride() { if (!process.env.PROPERTY) return; const [key, value] = process.env.PROPERTY.split(":"); if (value) { this.env[key] = value; process.env[key] = value; } } loadEnvVariables() { const currentEnvVars = this.env[this.envEnum]; if (currentEnvVars) { this.processEnvironmentVariables(currentEnvVars, ''); } const globalVars = Object.assign({}, this.env); delete globalVars[this.envEnum]; this.processEnvironmentVariables(globalVars, ''); } processEnvironmentVariables(obj, prefix) { Object.entries(obj).forEach(([key, value]) => { const fullKey = prefix ? `${prefix}.${key}` : key; if (this.isObject(value)) { this.processEnvironmentVariables(value, fullKey); return; } if (this.isLeveledKey(key)) { this.processLeveledVariable(key, value); return; } this.setEnvironmentVariable(fullKey, value); }); } isObject(value) { return typeof value === 'object' && value !== null; } isLeveledKey(key) { return key.includes('{') && key.includes('}'); } processLeveledVariable(key, value) { const [baseName] = key.split('{'); const levels = Number(key.split('{')[1].replace('}', '')); const path = this.buildRelativePath(levels); process.env[baseName.toUpperCase()] = path + value; } buildRelativePath(levels) { if (levels === 0) return './'; return '../'.repeat(levels); } setEnvironmentVariable(key, value) { const envKey = key.toUpperCase().replace(/\./g, '_'); if (value) { process.env[envKey] = value.toString(); } } static getProperty(key) { const leveledValue = this.findLeveledValue(key); if (leveledValue) { return this.getRelativePath(leveledValue.levels, leveledValue.key); } const value = this.getEnvValue(key); if (value) { return value; } const envKey = key.toUpperCase().replace(/\./g, '_'); return process.env[envKey] || ''; } static findLeveledValue(key) { if (!this.getInstance().env) return null; const matchingKeys = this.findKeysWithLevel(key); if (!matchingKeys.length) return null; const [keyWithLevel] = matchingKeys; const [_, levelPart] = keyWithLevel.split('{'); return { key: keyWithLevel, levels: Number(levelPart.replace('}', '')) }; } static findKeysWithLevel(key) { const hasLevel = (k) => k.includes(key) && k.includes('{') && k.includes('}'); const currentEnvKeys = Object.keys(this.getInstance().env[this.getInstance().envEnum] || {}); const matchingCurrentEnvKeys = currentEnvKeys.filter(hasLevel); if (matchingCurrentEnvKeys.length) return matchingCurrentEnvKeys; return Object.keys(this.getInstance().env).filter(hasLevel); } static getRelativePath(levels, key) { const value = this.getEnvValue(key); if (!value) return value; return this.buildRelativePath(levels) + value; } static buildRelativePath(levels) { if (levels === 0) return './'; return '../'.repeat(levels); } static reload() { this.instance.loadEnvironment(); } } exports.Environment = Environment; Environment.instance = new Environment;