/** * Shared route context — holds all dependencies needed by route modules. * Populated once by server.js at startup, then passed to each route factory. * * Usage in a route module: * module.exports = function(ctx) { * const router = require('express').Router(); * router.get('/status', ctx.asyncHandler(async (req, res) => { ... })); * return router; * }; * * Namespaces: ctx.docker.*, ctx.caddy.*, ctx.dns.*, ctx.session.*, * ctx.notification.*, ctx.tailscale.* */ const ctx = { // ── Namespaced groups ── docker: { client: null, // Dockerode instance pull: null, // dockerPull(imageName, timeoutMs) findContainer: null, // findContainerByName(name, opts) getUsedPorts: null, // getUsedPorts() → Set security: null, // dockerSecurity module }, caddy: { modify: null, // modifyCaddyfile(modifyFn) → {success, error?} read: null, // readCaddyfile() → string reload: null, // reloadCaddy(content) generateConfig: null, // generateCaddyConfig(subdomain, ip, port, opts) verifySite: null, // verifySiteAccessible(domain, maxAttempts) adminUrl: null, // CADDY_ADMIN_URL string filePath: null, // CADDYFILE_PATH string }, dns: { call: null, // callDns(server, apiPath, params) buildUrl: null, // buildDnsUrl(server, apiPath, params) requireToken: null, // requireDnsToken(providedToken) ensureToken: null, // ensureValidDnsToken() createRecord: null, // createDnsRecord(subdomain, ip) getToken: null, // () => dnsToken setToken: null, // (t) => { dnsToken = t } getTokenExpiry: null, // () => dnsTokenExpiry setTokenExpiry: null, // (e) => { dnsTokenExpiry = e } getTokenForServer: null, // getTokenForServer(serverIp) refresh: null, // refreshDnsToken() credentialsFile: null,// DNS_CREDENTIALS_FILE path }, session: { ipSessions: null, // Map of IP → session durations: null, // SESSION_DURATIONS map getClientIP: null, // getClientIP(req) create: null, // createIPSession(ip, duration) setCookie: null, // setSessionCookie(res, duration) clear: null, // clearIPSession(ip) clearCookie: null, // clearSessionCookie(res) isValid: null, // isSessionValid(req) }, notification: { getConfig: null, // () => notificationConfig saveConfig: null, // saveNotificationConfig() send: null, // sendNotification(event, title, message, type) sendDiscord: null, // sendDiscordNotification(title, message, type) sendTelegram: null, // sendTelegramNotification(title, message, type) sendNtfy: null, // sendNtfyNotification(title, message, type) getHistory: null, // () => notificationHistory clearHistory: null, // () => { notificationHistory = [] } startHealthDaemon: null, // startHealthCheckDaemon() stopHealthDaemon: null, // stopHealthCheckDaemon() checkHealth: null, // checkContainerHealth() getHealthState: null, // () => containerHealthState }, tailscale: { config: null, // tailscaleConfig object save: null, // saveTailscaleConfig() getStatus: null, // getTailscaleStatus() getLocalIP: null, // getLocalTailscaleIP() isTailscaleIP: null, // isTailscaleIP(ip) getAccessToken: null, // getTailscaleAccessToken() syncAPI: null, // syncFromTailscaleAPI() startSync: null, // startTailscaleSyncTimer() stopSync: null, // stopTailscaleSyncTimer() }, // ── Flat (shared across domains) ── app: null, siteConfig: null, servicesStateManager: null, configStateManager: null, credentialManager: null, authManager: null, // Feature modules healthChecker: null, updateManager: null, backupManager: null, resourceMonitor: null, auditLogger: null, portLockManager: null, // Templates APP_TEMPLATES: null, TEMPLATE_CATEGORIES: null, DIFFICULTY_LEVELS: null, // Shared helpers asyncHandler: null, errorResponse: null, ok: null, fetchT: null, log: null, logError: null, safeErrorMessage: null, buildDomain: null, getServiceById: null, readConfig: null, saveConfig: null, addServiceToConfig: null, validateURL: null, // Middleware strictLimiter: null, // TOTP (flat — used alongside session namespace) totpConfig: null, saveTotpConfig: null, // Config lifecycle loadSiteConfig: null, loadDnsCredentials: null, loadNotificationConfig: null, // Config paths (flat) SERVICES_FILE: null, CONFIG_FILE: null, TOTP_CONFIG_FILE: null, TAILSCALE_CONFIG_FILE: null, NOTIFICATIONS_FILE: null, ERROR_LOG_FILE: null, }; module.exports = ctx;