feat: payload cms
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 8s
Build & Deploy / 🧪 QA (push) Failing after 1m13s
Build & Deploy / 🏗️ Build (push) Failing after 5m53s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Smoke Test (push) Has been skipped
Build & Deploy / ⚡ Lighthouse (push) Has been skipped
Build & Deploy / ♿ WCAG (push) Has been skipped
Build & Deploy / 🛡️ Quality Gates (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 4s
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 8s
Build & Deploy / 🧪 QA (push) Failing after 1m13s
Build & Deploy / 🏗️ Build (push) Failing after 5m53s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Smoke Test (push) Has been skipped
Build & Deploy / ⚡ Lighthouse (push) Has been skipped
Build & Deploy / ♿ WCAG (push) Has been skipped
Build & Deploy / 🛡️ Quality Gates (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 4s
This commit is contained in:
@@ -11,9 +11,19 @@ import {
|
||||
import { PinoLoggerService } from './logging/pino-logger-service';
|
||||
import { config, getMaskedConfig } from '../config';
|
||||
|
||||
let singleton: AppServices | undefined;
|
||||
declare global {
|
||||
var __appServices: AppServices | undefined;
|
||||
}
|
||||
|
||||
// Add a local cache to prevent re-looking up globalThis frequently
|
||||
let serverSingleton: AppServices | undefined;
|
||||
|
||||
export function getServerAppServices(): AppServices {
|
||||
if (singleton) return singleton;
|
||||
if (serverSingleton) return serverSingleton;
|
||||
if (globalThis.__appServices) {
|
||||
serverSingleton = globalThis.__appServices;
|
||||
return serverSingleton;
|
||||
}
|
||||
|
||||
// Create logger first to log initialization
|
||||
const logger = new PinoLoggerService('server');
|
||||
@@ -74,9 +84,9 @@ export function getServerAppServices(): AppServices {
|
||||
level: config.logging.level,
|
||||
});
|
||||
|
||||
singleton = new AppServices(analytics, errors, cache, logger, notifications);
|
||||
globalThis.__appServices = new AppServices(analytics, errors, cache, logger, notifications);
|
||||
|
||||
logger.info('All application services initialized successfully');
|
||||
|
||||
return singleton;
|
||||
return globalThis.__appServices;
|
||||
}
|
||||
|
||||
@@ -9,65 +9,18 @@ import { PinoLoggerService } from './logging/pino-logger-service';
|
||||
import { NoopNotificationService } from './notifications/gotify-notification-service';
|
||||
import { config, getMaskedConfig } from '../config';
|
||||
|
||||
/**
|
||||
* Singleton instance of AppServices.
|
||||
*
|
||||
* In Next.js, module singletons are per-process (server) and per-tab (client).
|
||||
* This is sufficient for a small service layer and provides better performance
|
||||
* than creating new instances on every request.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
declare global {
|
||||
var __appServices: AppServices | undefined;
|
||||
}
|
||||
|
||||
let singleton: AppServices | undefined;
|
||||
|
||||
/**
|
||||
* Get the application services singleton.
|
||||
*
|
||||
* This function creates and caches the application services, including:
|
||||
* - Analytics service (Umami or no-op)
|
||||
* - Error reporting service (GlitchTip/Sentry or no-op)
|
||||
* - Cache service (in-memory)
|
||||
*
|
||||
* The services are configured based on environment variables:
|
||||
* - `UMAMI_WEBSITE_ID` - Enables Umami analytics
|
||||
* - `SENTRY_DSN` - Enables error reporting (server-side direct, client-side via relay)
|
||||
*
|
||||
* @returns {AppServices} The application services singleton
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Get services in a client component
|
||||
* import { getAppServices } from '@/lib/services/create-services';
|
||||
*
|
||||
* const services = getAppServices();
|
||||
* services.analytics.track('button_click', { button_id: 'cta' });
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Get services in a server component or API route
|
||||
* import { getAppServices } from '@/lib/services/create-services';
|
||||
*
|
||||
* const services = getAppServices();
|
||||
* await services.cache.set('key', 'value');
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Automatic service selection based on environment
|
||||
* // If UMAMI_WEBSITE_ID is set:
|
||||
* // services.analytics = UmamiAnalyticsService
|
||||
* // If not set:
|
||||
* // services.analytics = NoopAnalyticsService (safe no-op)
|
||||
* ```
|
||||
*
|
||||
* @see {@link UmamiAnalyticsService} for analytics implementation
|
||||
* @see {@link NoopAnalyticsService} for no-op fallback
|
||||
* @see {@link GlitchtipErrorReportingService} for error reporting
|
||||
* @see {@link MemoryCacheService} for caching
|
||||
*/
|
||||
export function getAppServices(): AppServices {
|
||||
// Return cached instance if available
|
||||
if (typeof window === 'undefined' && globalThis.__appServices) return globalThis.__appServices;
|
||||
if (singleton) return singleton;
|
||||
|
||||
// Create logger first to log initialization
|
||||
@@ -127,9 +80,6 @@ export function getAppServices(): AppServices {
|
||||
logger.info('Noop error reporting service initialized (error reporting disabled)');
|
||||
}
|
||||
|
||||
// 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();
|
||||
logger.info('Memory cache service initialized');
|
||||
|
||||
@@ -139,6 +89,11 @@ export function getAppServices(): AppServices {
|
||||
});
|
||||
|
||||
// Create and cache the singleton
|
||||
if (typeof window === 'undefined') {
|
||||
globalThis.__appServices = new AppServices(analytics, errors, cache, logger, notifications);
|
||||
return globalThis.__appServices;
|
||||
}
|
||||
|
||||
singleton = new AppServices(analytics, errors, cache, logger, notifications);
|
||||
|
||||
logger.info('All application services initialized successfully');
|
||||
|
||||
@@ -97,7 +97,7 @@ export class GlitchtipErrorReportingService implements ErrorReportingService {
|
||||
this.getSentry().then((Sentry) => Sentry.setTag(key, value));
|
||||
}
|
||||
|
||||
withScope<T>(fn: () => T, context?: Record<string, unknown>): T {
|
||||
withScope<T>(fn: () => T, _context?: Record<string, unknown>): T {
|
||||
if (!this.options.enabled) return fn();
|
||||
|
||||
// Since withScope mandates executing fn() synchronously to return T,
|
||||
|
||||
Reference in New Issue
Block a user