@roit/roit-environment
Version:
Facilitate environment management in node applications
211 lines (210 loc) • 7.45 kB
JavaScript
"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;