arena/server/config.js

174 lines
5.4 KiB
JavaScript

import fs from "node:fs";
import path from "node:path";
const DEFAULT_CONFIG = {
SERVER_HOST: "0.0.0.0",
SERVER_PORT: 9736,
MONGODB_HOST: "",
MONGODB_PORT: 27017,
MONGODB_DB: "arena",
MONGODB_USER: "",
MONGODB_PASS: "",
MONGODB_URI: "",
MONGODB_VISITOR_COLLECTION: "visitors",
MONGODB_ABOUT_COLLECTION: "about_content",
MONGODB_DAILY_DEATH_COLLECTION: "daily_death_stats",
MONGODB_DAILY_METRICS_COLLECTION: "daily_metrics",
MONGODB_DAILY_VISITOR_ACTIVITY_COLLECTION: "daily_visitor_activity",
MONGODB_MAX_POOL_SIZE: 10,
MONGODB_SERVER_SELECTION_TIMEOUT_MS: 5000,
DEATH_STATS_TIME_ZONE: "Asia/Seoul",
ANALYTICS_TIME_ZONE: "Asia/Seoul",
DAILY_ACTIVITY_RETENTION_DAYS: 60,
COOKIE_SECURE: false,
};
let config;
export function getConfig() {
if (!config) {
config = loadConfig();
}
return config;
}
export function loadConfig(filePath = path.resolve(process.cwd(), "config.json")) {
const rawConfig = fs.existsSync(filePath)
? JSON.parse(fs.readFileSync(filePath, "utf8"))
: {};
return normalizeConfig(rawConfig);
}
export function hasMongoConfig() {
const appConfig = getConfig();
return Boolean(appConfig.MONGODB_URI || appConfig.MONGODB_HOST);
}
export function getMongoUri() {
const appConfig = getConfig();
if (appConfig.MONGODB_URI) {
return appConfig.MONGODB_URI;
}
if (!appConfig.MONGODB_HOST) {
throw new Error("MongoDB configuration is required for arena tracking.");
}
const host = appConfig.MONGODB_HOST;
const port = Number(appConfig.MONGODB_PORT || DEFAULT_CONFIG.MONGODB_PORT);
const credentials = mongoCredentials(appConfig);
return `mongodb://${credentials}${host}:${port}`;
}
function normalizeConfig(rawConfig) {
const server = rawConfig.server || {};
const mongodb = rawConfig.mongodb || {};
return {
SERVER_HOST: stringValue(rawConfig.SERVER_HOST, server.host, DEFAULT_CONFIG.SERVER_HOST),
SERVER_PORT: numberValue(rawConfig.SERVER_PORT, server.port, DEFAULT_CONFIG.SERVER_PORT),
MONGODB_HOST: stringValue(rawConfig.MONGODB_HOST, mongodb.host, DEFAULT_CONFIG.MONGODB_HOST),
MONGODB_PORT: numberValue(rawConfig.MONGODB_PORT, mongodb.port, DEFAULT_CONFIG.MONGODB_PORT),
MONGODB_DB: stringValue(rawConfig.MONGODB_DB, mongodb.db, DEFAULT_CONFIG.MONGODB_DB),
MONGODB_USER: stringValue(rawConfig.MONGODB_USER, mongodb.user, DEFAULT_CONFIG.MONGODB_USER),
MONGODB_PASS: stringValue(rawConfig.MONGODB_PASS, mongodb.pass, DEFAULT_CONFIG.MONGODB_PASS),
MONGODB_URI: stringValue(rawConfig.MONGODB_URI, mongodb.uri, DEFAULT_CONFIG.MONGODB_URI),
MONGODB_VISITOR_COLLECTION: stringValue(
rawConfig.MONGODB_VISITOR_COLLECTION,
mongodb.visitorCollection,
DEFAULT_CONFIG.MONGODB_VISITOR_COLLECTION,
),
MONGODB_ABOUT_COLLECTION: stringValue(
rawConfig.MONGODB_ABOUT_COLLECTION,
mongodb.aboutCollection,
DEFAULT_CONFIG.MONGODB_ABOUT_COLLECTION,
),
MONGODB_DAILY_DEATH_COLLECTION: stringValue(
rawConfig.MONGODB_DAILY_DEATH_COLLECTION,
mongodb.dailyDeathCollection,
DEFAULT_CONFIG.MONGODB_DAILY_DEATH_COLLECTION,
),
MONGODB_DAILY_METRICS_COLLECTION: stringValue(
rawConfig.MONGODB_DAILY_METRICS_COLLECTION,
mongodb.dailyMetricsCollection,
DEFAULT_CONFIG.MONGODB_DAILY_METRICS_COLLECTION,
),
MONGODB_DAILY_VISITOR_ACTIVITY_COLLECTION: stringValue(
rawConfig.MONGODB_DAILY_VISITOR_ACTIVITY_COLLECTION,
mongodb.dailyVisitorActivityCollection,
DEFAULT_CONFIG.MONGODB_DAILY_VISITOR_ACTIVITY_COLLECTION,
),
MONGODB_MAX_POOL_SIZE: numberValue(
rawConfig.MONGODB_MAX_POOL_SIZE,
mongodb.maxPoolSize,
DEFAULT_CONFIG.MONGODB_MAX_POOL_SIZE,
),
MONGODB_SERVER_SELECTION_TIMEOUT_MS: numberValue(
rawConfig.MONGODB_SERVER_SELECTION_TIMEOUT_MS,
mongodb.serverSelectionTimeoutMs,
DEFAULT_CONFIG.MONGODB_SERVER_SELECTION_TIMEOUT_MS,
),
DEATH_STATS_TIME_ZONE: stringValue(
rawConfig.DEATH_STATS_TIME_ZONE,
rawConfig.TIME_ZONE,
mongodb.deathStatsTimeZone,
DEFAULT_CONFIG.DEATH_STATS_TIME_ZONE,
),
ANALYTICS_TIME_ZONE: stringValue(
rawConfig.ANALYTICS_TIME_ZONE,
rawConfig.TIME_ZONE,
mongodb.analyticsTimeZone,
DEFAULT_CONFIG.ANALYTICS_TIME_ZONE,
),
DAILY_ACTIVITY_RETENTION_DAYS: numberValue(
rawConfig.DAILY_ACTIVITY_RETENTION_DAYS,
mongodb.dailyActivityRetentionDays,
DEFAULT_CONFIG.DAILY_ACTIVITY_RETENTION_DAYS,
),
COOKIE_SECURE: booleanValue(rawConfig.COOKIE_SECURE, server.cookieSecure, DEFAULT_CONFIG.COOKIE_SECURE),
};
}
function mongoCredentials(appConfig) {
if (!appConfig.MONGODB_USER) {
return "";
}
const user = encodeURIComponent(appConfig.MONGODB_USER);
const pass = encodeURIComponent(appConfig.MONGODB_PASS || "");
return `${user}:${pass}@`;
}
function stringValue(...values) {
const value = values.find((candidate) => typeof candidate === "string" && candidate.length > 0);
return value ?? "";
}
function numberValue(...values) {
const value = values.find((candidate) => {
const numericValue = Number(candidate);
return Number.isFinite(numericValue) && numericValue > 0;
});
return Number(value);
}
function booleanValue(...values) {
const value = values.find((candidate) => typeof candidate === "boolean" || candidate === "true" || candidate === "false");
if (value === "true") {
return true;
}
if (value === "false") {
return false;
}
return Boolean(value);
}