Files
scoreko-electron-dev/src/main/config/runtime-config.ts
T
2026-02-24 13:08:25 +01:00

81 lines
2.9 KiB
TypeScript

export type AppRuntimeConfig = {
title: string;
userModelId: string;
userDataDirectoryName: string;
iconPathOverride?: string;
nodecgPort: string;
bundleName: string;
mainDashboardRoute: string;
loadingDashboardRoute: string;
loadDelayMs: number;
startupTimeoutMs: number;
nodecgKillTimeoutMs: number;
};
const MIN_TCP_PORT = 1;
const MAX_TCP_PORT = 65535;
export function getRuntimeConfig(): AppRuntimeConfig {
// Centralized defaults keep local development and packaged builds consistent.
return {
title: getEnv("SCOREKO_APP_TITLE", "Scoreko"),
userModelId: getEnv("SCOREKO_APP_USER_MODEL_ID", "com.scoreko.desktop"),
userDataDirectoryName: getEnv("SCOREKO_APP_USER_DATA_DIRECTORY", "scoreko"),
iconPathOverride: getOptionalEnv("SCOREKO_APP_ICON_PATH"),
nodecgPort: parseEnvPort("NODECG_PORT", "9090"),
bundleName: getEnv("NODECG_BUNDLE_NAME", "scoreko-dev"),
mainDashboardRoute: getEnv("SCOREKO_DASHBOARD_ROUTE", "dashboard/scoreko-dev/main.html?standalone=true"),
loadingDashboardRoute: getEnv("SCOREKO_LOADING_ROUTE", "dashboard/loading/main.html?standalone=true"),
loadDelayMs: parseEnvIntInRange("ELECTRON_LOAD_DELAY_MS", 10000, 0, 600000),
startupTimeoutMs: parseEnvIntInRange("NODECG_STARTUP_TIMEOUT_MS", 30000, 1000, 600000),
nodecgKillTimeoutMs: parseEnvIntInRange("NODECG_KILL_TIMEOUT_MS", 2500, 0, 120000),
};
}
export function getOptionalEnv(name: string): string | undefined {
const value = process.env[name]?.trim();
return value && value.length > 0 ? value : undefined;
}
export function getEnv(name: string, fallback: string): string {
return getOptionalEnv(name) ?? fallback;
}
export function parseEnvInt(name: string, fallback: number): number {
const rawValue = process.env[name];
if (!rawValue) {
return fallback;
}
const parsedValue = Number.parseInt(rawValue, 10);
return Number.isFinite(parsedValue) ? parsedValue : fallback;
}
export function parseEnvIntInRange(name: string, fallback: number, min: number, max: number): number {
// We throw here instead of silently coercing to avoid hidden misconfiguration in production.
const rawValue = process.env[name];
if (!rawValue) {
return fallback;
}
const parsedValue = Number.parseInt(rawValue, 10);
if (!Number.isFinite(parsedValue) || parsedValue < min || parsedValue > max) {
throw new Error(`The ${name} variable must be an integer between ${min} and ${max}. Received value: '${rawValue}'.`);
}
return parsedValue;
}
export function parseEnvPort(name: string, fallback: string): string {
const rawValue = getEnv(name, fallback);
const parsedValue = Number.parseInt(rawValue, 10);
if (!Number.isFinite(parsedValue) || parsedValue < MIN_TCP_PORT || parsedValue > MAX_TCP_PORT) {
throw new Error(
`The ${name} variable must be a valid TCP port (${MIN_TCP_PORT}-${MAX_TCP_PORT}). Received value: '${rawValue}'.`,
);
}
return String(parsedValue);
}