import { AppServices } from "./app-services"; import { NoopAnalyticsService } from "./analytics/noop-analytics-service"; import { UmamiAnalyticsService } from "./analytics/umami-analytics-service"; import { MemoryCacheService } from "./cache/memory-cache-service"; import { GlitchtipErrorReportingService } from "./errors/glitchtip-error-reporting-service"; import { NoopErrorReportingService } from "./errors/noop-error-reporting-service"; import { GotifyNotificationService, NoopNotificationService, } from "./notifications/gotify-notification-service"; import { PinoLoggerService } from "./logging/pino-logger-service"; import { config, getMaskedConfig } from "../config"; let singleton: AppServices | undefined; export function getServerAppServices(): AppServices { if (singleton) return singleton; // Create logger first to log initialization const logger = new PinoLoggerService("server"); logger.info("Initializing server application services", { environment: getMaskedConfig(), timestamp: new Date().toISOString(), }); logger.info("Service configuration", { umamiEnabled: config.analytics.umami.enabled, sentryEnabled: config.errors.glitchtip.enabled, mailEnabled: Boolean(config.mail.host && config.mail.user), gotifyEnabled: config.notifications.gotify.enabled, }); const analytics = config.analytics.umami.enabled ? new UmamiAnalyticsService({ enabled: true }) : new NoopAnalyticsService(); if (config.analytics.umami.enabled) { logger.info("Umami analytics service initialized"); } else { logger.info("Noop analytics service initialized (analytics disabled)"); } const notifications = config.notifications.gotify.enabled ? new GotifyNotificationService({ url: config.notifications.gotify.url!, token: config.notifications.gotify.token!, enabled: true, }) : new NoopNotificationService(); if (config.notifications.gotify.enabled) { logger.info("Gotify notification service initialized"); } else { logger.info( "Noop notification service initialized (notifications disabled)", ); } const errors = config.errors.glitchtip.enabled ? new GlitchtipErrorReportingService({ enabled: true }, notifications) : new NoopErrorReportingService(); if (config.errors.glitchtip.enabled) { logger.info("GlitchTip error reporting service initialized", { dsnPresent: Boolean(config.errors.glitchtip.dsn), }); } else { logger.info( "Noop error reporting service initialized (error reporting disabled)", ); } const cache = new MemoryCacheService(); logger.info("Memory cache service initialized"); logger.info("Pino logger service initialized", { name: "server", level: config.logging.level, }); singleton = new AppServices(analytics, errors, cache, logger, notifications); logger.info("All application services initialized successfully"); return singleton; }