refactor(config): Extract configuration into src/config/ module

- Create src/config/paths.js for all file paths and env vars
- Create src/config/site.js for site configuration loading
- Create src/config/index.js as unified config export
- Prepare for server.js modularization (Phase 2.1)

Part of deslopification roadmap: break 1997-line server.js into layers
This commit is contained in:
Krystie
2026-03-29 19:36:43 -07:00
parent ecedf0c132
commit 6c3d2baede
3 changed files with 159 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
/**
* Site configuration loader
* Loads and manages site-wide settings from config.json
*/
const fs = require('fs');
const { validateConfig } = require('../../config-schema');
const { CADDY } = require('../../constants');
let siteConfig = {
tld: '.home',
caName: '',
dnsServerIp: '',
dnsServerPort: CADDY.DEFAULT_DNS_PORT,
dashboardHost: '',
timezone: 'UTC',
dnsServers: {},
configurationType: 'homelab',
domain: '',
routingMode: 'subdomain'
};
function loadSiteConfig(CONFIG_FILE, log) {
try {
if (fs.existsSync(CONFIG_FILE)) {
const raw = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
// Validate config and log any issues
const { valid, errors: configErrors, warnings: configWarnings } = validateConfig(raw);
if (log && log.warn) {
if (!valid) {
log.warn('config', 'Config validation errors', { errors: configErrors });
}
for (const w of configWarnings) {
log.warn('config', w);
}
}
siteConfig.tld = raw.tld || '.home';
if (!siteConfig.tld.startsWith('.')) siteConfig.tld = '.' + siteConfig.tld;
siteConfig.caName = raw.caName || '';
siteConfig.dnsServerIp = (raw.dns && raw.dns.ip) || '';
siteConfig.dnsServerPort = (raw.dns && raw.dns.port) || CADDY.DEFAULT_DNS_PORT;
siteConfig.dashboardHost = raw.dashboardHost || `status${siteConfig.tld}`;
siteConfig.timezone = raw.timezone || 'UTC';
siteConfig.dnsServers = raw.dnsServers || {};
siteConfig.configurationType = raw.configurationType || 'homelab';
siteConfig.domain = raw.domain || '';
siteConfig.routingMode = raw.routingMode || 'subdomain';
siteConfig.pylon = raw.pylon || null;
}
} catch (e) {
if (log && log.error) {
log.error('config', 'Failed to load site config', { error: e.message });
}
}
}
/** Build a domain from subdomain + configured TLD or public domain */
function buildDomain(subdomain) {
if (siteConfig.configurationType === 'public' && siteConfig.domain) {
return `${subdomain}.${siteConfig.domain}`;
}
return `${subdomain}${siteConfig.tld}`;
}
/** Build full service URL (protocol + host + path) */
function buildServiceUrl(subdomain) {
if (siteConfig.routingMode === 'subdirectory' && siteConfig.domain) {
return `https://${siteConfig.domain}/${subdomain}`;
}
return `https://${buildDomain(subdomain)}`;
}
module.exports = {
siteConfig,
loadSiteConfig,
buildDomain,
buildServiceUrl,
};