feat: read config from env if config.json is not found
This commit is contained in:
parent
05706007f1
commit
a462b6af1b
6 changed files with 141 additions and 5 deletions
21
.env.example
Normal file
21
.env.example
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
ACORE_ARMORY_AOWOW_URL="https://wotlkdb.com"
|
||||
ACORE_ARMORY_WEBSITE_URL="https://mywebsite.com"
|
||||
ACORE_ARMORY_WEBSITE_NAME="My Website"
|
||||
ACORE_ARMORY_IFRAME_MODE__ENABLED=0
|
||||
ACORE_ARMORY_IFRAME_MODE__URL="https://mywebsite.com/armory"
|
||||
ACORE_ARMORY_LOAD_DBCS=1
|
||||
ACORE_ARMORY_HIDE_GAME_MASTERS=1
|
||||
ACORE_ARMORY_REALMS__0__NAME="AzerothCore"
|
||||
ACORE_ARMORY_REALMS__0__REALM_ID=1
|
||||
ACORE_ARMORY_REALMS__0__AUTH_DATABASE="acore_auth"
|
||||
ACORE_ARMORY_REALMS__0__CHARACTERS_DATABASE__HOST="localhost"
|
||||
ACORE_ARMORY_REALMS__0__CHARACTERS_DATABASE__PORT=3306
|
||||
ACORE_ARMORY_REALMS__0__CHARACTERS_DATABASE__USER="root"
|
||||
ACORE_ARMORY_REALMS__0__CHARACTERS_DATABASE__PASSWORD="root"
|
||||
ACORE_ARMORY_REALMS__0__CHARACTERS_DATABASE__DATABASE="acore_characters"
|
||||
ACORE_ARMORY_WORLD_DATABASE__HOST="localhost"
|
||||
ACORE_ARMORY_WORLD_DATABASE__PORT=3306
|
||||
ACORE_ARMORY_WORLD_DATABASE__USER="root"
|
||||
ACORE_ARMORY_WORLD_DATABASE__PASSWORD="root"
|
||||
ACORE_ARMORY_WORLD_DATABASE__DATABASE="acore_world"
|
||||
ACORE_ARMORY_DB_QUERY_TIMEOUT=10000
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -11,6 +11,7 @@ data/*
|
|||
|
||||
# Configuration
|
||||
config.json
|
||||
.env
|
||||
|
||||
# Log files
|
||||
*.log
|
||||
|
|
|
|||
18
package-lock.json
generated
18
package-lock.json
generated
|
|
@ -1,17 +1,18 @@
|
|||
{
|
||||
"name": "azerothcore-armory",
|
||||
"version": "0.10.0",
|
||||
"version": "0.11.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "azerothcore-armory",
|
||||
"version": "0.10.0",
|
||||
"version": "0.11.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@supercharge/promise-pool": "^2.1.0",
|
||||
"camelcase": "^6.3.0",
|
||||
"cli-progress": "^3.10.0",
|
||||
"dotenv": "^16.0.0",
|
||||
"express": "^4.17.3",
|
||||
"express-handlebars": "^6.0.2",
|
||||
"glob": "^7.2.0",
|
||||
|
|
@ -1589,6 +1590,14 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz",
|
||||
"integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/duplexer3": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
|
||||
|
|
@ -6394,6 +6403,11 @@
|
|||
"is-obj": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"dotenv": {
|
||||
"version": "16.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz",
|
||||
"integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q=="
|
||||
},
|
||||
"duplexer3": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "azerothcore-armory",
|
||||
"version": "0.10.0",
|
||||
"version": "0.11.0",
|
||||
"description": "",
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
|
|
@ -32,6 +32,7 @@
|
|||
"@supercharge/promise-pool": "^2.1.0",
|
||||
"camelcase": "^6.3.0",
|
||||
"cli-progress": "^3.10.0",
|
||||
"dotenv": "^16.0.0",
|
||||
"express": "^4.17.3",
|
||||
"express-handlebars": "^6.0.2",
|
||||
"glob": "^7.2.0",
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue