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 { RedisCacheService } from './cache/redis-cache-service'; import { GlitchtipErrorReportingService } from './errors/glitchtip-error-reporting-service'; import { NoopErrorReportingService } from './errors/noop-error-reporting-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, redisEnabled: config.cache.redis.enabled, mailEnabled: Boolean(config.mail.host && config.mail.user), }); 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 errors = config.errors.glitchtip.enabled ? new GlitchtipErrorReportingService({ enabled: true }) : new NoopErrorReportingService(); if (config.errors.glitchtip.enabled) { logger.info('GlitchTip error reporting service initialized'); } else { logger.info('Noop error reporting service initialized (error reporting disabled)'); } const cache = config.cache.redis.enabled && config.cache.redis.url ? new RedisCacheService({ url: config.cache.redis.url, keyPrefix: config.cache.redis.keyPrefix, }) : new MemoryCacheService(); if (config.cache.redis.enabled) { logger.info('Redis cache service initialized', { keyPrefix: config.cache.redis.keyPrefix }); } else { logger.info('Memory cache service initialized (Redis not configured)'); } logger.info('Pino logger service initialized', { name: 'server', level: config.logging.level, }); singleton = new AppServices(analytics, errors, cache, logger); logger.info('All application services initialized successfully'); return singleton; }