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'; let singleton: AppServices | undefined; export function getAppServices(): AppServices { // In Next.js, module singletons are per-process (server) and per-tab (client). // This is good enough for a small service layer. if (singleton) return singleton; const umamiEnabled = Boolean(process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID); const sentryClientEnabled = Boolean(process.env.NEXT_PUBLIC_SENTRY_DSN); const sentryServerEnabled = Boolean(process.env.SENTRY_DSN); const analytics = umamiEnabled ? new UmamiAnalyticsService({ enabled: true }) : new NoopAnalyticsService(); // Enable GlitchTip/Sentry only when a DSN is present for the active runtime. const errors = typeof window === 'undefined' ? sentryServerEnabled ? new GlitchtipErrorReportingService({ enabled: true }) : new NoopErrorReportingService() : sentryClientEnabled ? new GlitchtipErrorReportingService({ enabled: true }) : new NoopErrorReportingService(); // IMPORTANT: This module is imported by client components. // Do not import Node-only modules (like the `redis` client) here. // Use [`getServerAppServices()`](lib/services/create-services.server.ts:1) on the server. const cache = new MemoryCacheService(); singleton = new AppServices(analytics, errors, cache); return singleton; }