feat: read config from env if config.json is not found

This commit is contained in:
Axel Cocat 2022-03-14 22:42:28 +01:00
parent 05706007f1
commit a462b6af1b
6 changed files with 141 additions and 5 deletions

View file

@ -34,9 +34,19 @@ export class Config {
public worldDatabase: IDatabaseConfig;
public dbQueryTimeout: number;
private static envPrefix: string = "ACORE_ARMORY";
private static checkedMissingField: boolean = false;
public static async load(logger: winston.Logger): Promise<Config> {
try {
await fsp.access("config.json");
return await Config.loadFromFile(logger);
} catch (err) {
return await Config.loadFromEnv(logger);
}
}
private static async loadFromFile(logger: winston.Logger): Promise<Config> {
const json: Buffer = await fsp.readFile("config.json");
const config = JSON.parse(json.toString()) as Config;
@ -50,13 +60,101 @@ export class Config {
return config;
}
private static async loadFromEnv(logger: winston.Logger): Promise<Config> {
const config = {};
const json = await fsp.readFile("config.default.json");
const defaultConfig = JSON.parse(json.toString());
Config.loadObjFromEnv(logger, config, defaultConfig);
Config.checkedMissingField = true;
return config as Config;
}
private static loadObjFromEnv(logger: winston.Logger, obj: object, model: object, parentName: string = "") {
if (parentName !== "") {
parentName += ".";
}
for (const field in model) {
if (!model.hasOwnProperty(field)) {
continue;
}
if (Array.isArray(model[field])) {
obj[field] = Config.loadArrayFromEnv(logger, model[field][0], parentName + field);
} else if (typeof model[field] === "object") {
obj[field] = {};
Config.loadObjFromEnv(logger, obj[field], model[field], parentName + field);
} else if (!obj.hasOwnProperty(field)) {
const key = Config.getEnvKey(parentName + field);
if (process.env.hasOwnProperty(key)) {
obj[field] = Config.parseEnvValue(process.env[key], model[field]);
} else if (!Config.checkedMissingField) {
logger.warn(`Config field ${key} is missing from .env!`);
}
}
}
}
private static loadArrayFromEnv(logger: winston.Logger, model: any, parentName: string = ""): any[] {
if (parentName !== "") {
parentName += ".";
}
const arr = [];
let i = 0;
while (true) {
const key = Config.getEnvKey(parentName + i);
const found = Object.keys(process.env).some(k => k.startsWith(key));
if (!found) {
break;
}
if (Array.isArray(model)) {
arr.push(Config.loadArrayFromEnv(logger, model[0], parentName + i));
} else if (typeof model === "object") {
const obj = {};
Config.loadObjFromEnv(logger, obj, model, parentName + i);
if (Object.keys(obj).length > 0) {
arr.push(obj);
}
} else if (process.env.hasOwnProperty(key)) {
arr.push(Config.parseEnvValue(process.env[key], model));
} else {
break;
}
++i;
}
return arr;
}
private static getEnvKey(key: string): string {
return Config.envPrefix + "_" + key
.replace(/\./g, "__")
.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`)
.toUpperCase();
}
private static parseEnvValue(value: string, model: any): any {
const type = typeof model;
const lower = value.toLowerCase();
if (type === "boolean") {
return lower === "true" || value === "1";
}
if (type === "number") {
return parseFloat(value);
}
return value;
}
private static checkAllMissingFields(logger: winston.Logger, obj: object, model: object, parentName: string = "") {
const missing = Config.hasMissingFields(obj, model);
if (parentName !== "") {
parentName += ".";
}
for (const field of missing) {
logger.warn(`Field ${parentName}${field} is missing in config.json!`);
logger.warn(`Field ${parentName}${field} is missing from config.json!`);
}
for (const key in model) {
if (typeof model[key] === "object" && obj.hasOwnProperty(key)) {

View file

@ -1,10 +1,11 @@
import "dotenv/config";
import { Armory } from "./Armory";
async function main(): Promise<void> {
require("source-map-support").install();
const armory = new Armory();
armory.start();
await armory.start();
}
main();