view models

This commit is contained in:
2025-12-18 14:04:31 +01:00
parent 4f99098b32
commit 61f675d991
9 changed files with 95 additions and 19 deletions

View File

@@ -0,0 +1,8 @@
import { ErrorReporter } from "@core/shared/application";
export class ConsoleErrorReporter implements ErrorReporter {
report(error: Error, context?: unknown): void {
const timestamp = new Date().toISOString();
console.error(`[${timestamp}] Error reported:`, error.message, { error, context });
}
}

View File

@@ -1,20 +1,26 @@
import { Logger } from "@core/shared/application"; import { Logger } from "@core/shared/application";
export class ConsoleLogger implements Logger { export class ConsoleLogger implements Logger {
debug(message: string, ...args: any[]): void { private formatMessage(level: string, message: string, context?: unknown): string {
console.debug(message, ...args); const timestamp = new Date().toISOString();
const contextStr = context ? ` | ${JSON.stringify(context)}` : '';
return `[${timestamp}] ${level.toUpperCase()}: ${message}${contextStr}`;
} }
info(message: string, ...args: any[]): void { debug(message: string, context?: unknown): void {
console.info(message, ...args); console.debug(this.formatMessage('debug', message, context));
} }
warn(message: string, ...args: any[]): void { info(message: string, context?: unknown): void {
console.warn(message, ...args); console.info(this.formatMessage('info', message, context));
} }
error(message: string, ...args: any[]): void { warn(message: string, context?: unknown): void {
console.error(message, ...args); console.warn(this.formatMessage('warn', message, context));
} }
error(message: string, error?: Error, context?: unknown): void {
const errorStr = error ? ` | Error: ${error.message}` : '';
console.error(this.formatMessage('error', message, context) + errorStr);
}
} }

View File

@@ -5,14 +5,23 @@
* error handling, and authentication. * error handling, and authentication.
*/ */
import { Logger } from '../../interfaces/Logger';
import { ErrorReporter } from '../../interfaces/ErrorReporter';
export class BaseApiClient { export class BaseApiClient {
private baseUrl: string; private baseUrl: string;
private errorReporter: ErrorReporter;
private logger: Logger;
constructor(baseUrl: string) { constructor(baseUrl: string, errorReporter: ErrorReporter, logger: Logger) {
this.baseUrl = baseUrl; this.baseUrl = baseUrl;
this.errorReporter = errorReporter;
this.logger = logger;
} }
protected async request<T>(method: string, path: string, data?: object): Promise<T> { protected async request<T>(method: string, path: string, data?: object): Promise<T> {
this.logger.info(`${method} ${path}`);
const headers: HeadersInit = { const headers: HeadersInit = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}; };
@@ -36,7 +45,9 @@ export class BaseApiClient {
} catch { } catch {
// Keep default error message // Keep default error message
} }
throw new Error(errorData.message || `API request failed with status ${response.status}`); const error = new Error(errorData.message || `API request failed with status ${response.status}`);
this.errorReporter.report(error);
throw error;
} }
const text = await response.text(); const text = await response.text();

View File

@@ -0,0 +1,8 @@
import { ErrorReporter } from '../../interfaces/ErrorReporter';
export class ConsoleErrorReporter implements ErrorReporter {
report(error: Error, context?: unknown): void {
const timestamp = new Date().toISOString();
console.error(`[${timestamp}] Error reported:`, error.message, { error, context });
}
}

View File

@@ -0,0 +1,26 @@
import { Logger } from '../../interfaces/Logger';
export class ConsoleLogger implements Logger {
private formatMessage(level: string, message: string, context?: unknown): string {
const timestamp = new Date().toISOString();
const contextStr = context ? ` | ${JSON.stringify(context)}` : '';
return `[${timestamp}] ${level.toUpperCase()}: ${message}${contextStr}`;
}
debug(message: string, context?: unknown): void {
console.debug(this.formatMessage('debug', message, context));
}
info(message: string, context?: unknown): void {
console.info(this.formatMessage('info', message, context));
}
warn(message: string, context?: unknown): void {
console.warn(this.formatMessage('warn', message, context));
}
error(message: string, error?: Error, context?: unknown): void {
const errorStr = error ? ` | Error: ${error.message}` : '';
console.error(this.formatMessage('error', message, context) + errorStr);
}
}

View File

@@ -0,0 +1,3 @@
export interface ErrorReporter {
report(error: Error, context?: unknown): void;
}

View File

@@ -0,0 +1,6 @@
export interface Logger {
debug(message: string, context?: unknown): void;
info(message: string, context?: unknown): void;
warn(message: string, context?: unknown): void;
error(message: string, error?: Error, context?: unknown): void;
}

View File

@@ -7,6 +7,8 @@ import { PaymentsApiClient } from '../api/payments/PaymentsApiClient';
import { AuthApiClient } from '../api/auth/AuthApiClient'; import { AuthApiClient } from '../api/auth/AuthApiClient';
import { AnalyticsApiClient } from '../api/analytics/AnalyticsApiClient'; import { AnalyticsApiClient } from '../api/analytics/AnalyticsApiClient';
import { MediaApiClient } from '../api/media/MediaApiClient'; import { MediaApiClient } from '../api/media/MediaApiClient';
import { ConsoleErrorReporter } from '../infrastructure/logging/ConsoleErrorReporter';
import { ConsoleLogger } from '../infrastructure/logging/ConsoleLogger';
// Services // Services
import { RaceService } from './races/RaceService'; import { RaceService } from './races/RaceService';
@@ -37,6 +39,9 @@ import { SessionService } from './auth/SessionService';
* Services now directly instantiate View Models instead of using Presenters. * Services now directly instantiate View Models instead of using Presenters.
*/ */
export class ServiceFactory { export class ServiceFactory {
private readonly errorReporter = new ConsoleErrorReporter();
private readonly logger = new ConsoleLogger();
private readonly apiClients: { private readonly apiClients: {
races: RacesApiClient; races: RacesApiClient;
drivers: DriversApiClient; drivers: DriversApiClient;
@@ -52,15 +57,15 @@ export class ServiceFactory {
constructor(baseUrl: string) { constructor(baseUrl: string) {
// Initialize API clients // Initialize API clients
this.apiClients = { this.apiClients = {
races: new RacesApiClient(baseUrl), races: new RacesApiClient(baseUrl, this.errorReporter, this.logger),
drivers: new DriversApiClient(baseUrl), drivers: new DriversApiClient(baseUrl, this.errorReporter, this.logger),
teams: new TeamsApiClient(baseUrl), teams: new TeamsApiClient(baseUrl, this.errorReporter, this.logger),
leagues: new LeaguesApiClient(baseUrl), leagues: new LeaguesApiClient(baseUrl, this.errorReporter, this.logger),
sponsors: new SponsorsApiClient(baseUrl), sponsors: new SponsorsApiClient(baseUrl, this.errorReporter, this.logger),
payments: new PaymentsApiClient(baseUrl), payments: new PaymentsApiClient(baseUrl, this.errorReporter, this.logger),
auth: new AuthApiClient(baseUrl), auth: new AuthApiClient(baseUrl, this.errorReporter, this.logger),
analytics: new AnalyticsApiClient(baseUrl), analytics: new AnalyticsApiClient(baseUrl, this.errorReporter, this.logger),
media: new MediaApiClient(baseUrl), media: new MediaApiClient(baseUrl, this.errorReporter, this.logger),
}; };
} }

View File

@@ -0,0 +1,3 @@
export interface ErrorReporter {
report(error: Error, context?: unknown): void;
}