/** * Infrastructure Adapter: InMemoryResultRepository * * In-memory implementation of IResultRepository. * Stores data in Map structure with UUID generation. */ import { Result } from '@core/racing/domain/entities/result/Result'; import type { ResultRepository } from '@core/racing/domain/repositories/ResultRepository'; import type { RaceRepository } from '@core/racing/domain/repositories/RaceRepository'; import type { Logger } from '@core/shared/domain/Logger'; import { v4 as uuidv4 } from 'uuid'; export class InMemoryResultRepository implements ResultRepository { private results: Map; private raceRepository: RaceRepository | null; private readonly logger: Logger; constructor(logger: Logger, raceRepository?: RaceRepository | null) { this.logger = logger; this.logger.info('[InMemoryResultRepository] Initialized.'); this.results = new Map(); this.raceRepository = raceRepository ?? null; } async findById(id: string): Promise { this.logger.debug(`[InMemoryResultRepository] Finding result by id: ${id}`); try { const result = this.results.get(id) ?? null; if (result) { this.logger.info(`[InMemoryResultRepository] Found result with id: ${id}.`); } else { this.logger.warn(`[InMemoryResultRepository] Result with id ${id} not found.`); } return result; } catch (error) { this.logger.error(`[InMemoryResultRepository] Error finding result by id ${id}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } async findAll(): Promise { this.logger.debug('[InMemoryResultRepository] Finding all results.'); try { const results = Array.from(this.results.values()); this.logger.info(`[InMemoryResultRepository] Found ${results.length} results.`); return results; } catch (error) { this.logger.error('[InMemoryResultRepository] Error finding all results:', error instanceof Error ? error : new Error(String(error))); throw error; } } async findByRaceId(raceId: string): Promise { this.logger.debug(`[InMemoryResultRepository] Finding results for race id: ${raceId}`); try { const results = Array.from(this.results.values()) .filter(result => result.raceId.toString() === raceId) .sort((a, b) => a.position.toNumber() - b.position.toNumber()); this.logger.info(`[InMemoryResultRepository] Found ${results.length} results for race id: ${raceId}.`); return results; } catch (error) { this.logger.error(`[InMemoryResultRepository] Error finding results for race id ${raceId}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } async findByDriverId(driverId: string): Promise { this.logger.debug(`[InMemoryResultRepository] Finding results for driver id: ${driverId}`); try { const results = Array.from(this.results.values()) .filter(result => result.driverId.toString() === driverId); this.logger.info(`[InMemoryResultRepository] Found ${results.length} results for driver id: ${driverId}.`); return results; } catch (error) { this.logger.error(`[InMemoryResultRepository] Error finding results for driver id ${driverId}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } async findByDriverIdAndLeagueId(driverId: string, leagueId: string): Promise { this.logger.debug(`[InMemoryResultRepository] Finding results for driver id: ${driverId} and league id: ${leagueId}`); try { if (!this.raceRepository) { this.logger.warn('[InMemoryResultRepository] Race repository not provided to InMemoryResultRepository. Skipping league-filtered search.'); return []; } const leagueRaces = await this.raceRepository.findByLeagueId(leagueId); const leagueRaceIds = new Set(leagueRaces.map((race: any) => race.id)); this.logger.debug(`[InMemoryResultRepository] Found ${leagueRaces.length} races in league ${leagueId}.`); const results = Array.from(this.results.values()) .filter(result => result.driverId.toString() === driverId && leagueRaceIds.has(result.raceId.toString()) ); this.logger.info(`[InMemoryResultRepository] Found ${results.length} results for driver ${driverId} in league ${leagueId}.`); return results; } catch (error) { this.logger.error(`[InMemoryResultRepository] Error finding results for driver ${driverId} and league ${leagueId}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } async create(result: Result): Promise { this.logger.debug(`[InMemoryResultRepository] Creating result: ${result.id}`); try { if (await this.exists(result.id)) { this.logger.warn(`[InMemoryResultRepository] Result with ID ${result.id} already exists. Throwing error.`); throw new Error(`Result with ID ${result.id} already exists`); } this.results.set(result.id, result); this.logger.info(`[InMemoryResultRepository] Result ${result.id} created successfully.`); return result; } catch (error) { this.logger.error(`[InMemoryResultRepository] Error creating result ${result.id}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } async createMany(results: Result[]): Promise { this.logger.debug(`[InMemoryResultRepository] Creating ${results.length} results.`); try { const created: Result[] = []; for (const result of results) { if (await this.exists(result.id)) { this.logger.warn(`[InMemoryResultRepository] Result with ID ${result.id} already exists. Skipping creation.`); // In a real system, decide if this should throw or log and skip continue; } this.results.set(result.id, result); created.push(result); } this.logger.info(`[InMemoryResultRepository] Created ${created.length} results successfully.`); return created; } catch (error) { this.logger.error(`[InMemoryResultRepository] Error creating many results:`, error instanceof Error ? error : new Error(String(error))); throw error; } } async update(result: Result): Promise { this.logger.debug(`[InMemoryResultRepository] Updating result: ${result.id}`); try { if (!await this.exists(result.id)) { this.logger.warn(`[InMemoryResultRepository] Result with ID ${result.id} not found for update. Throwing error.`); throw new Error(`Result with ID ${result.id} not found`); } this.results.set(result.id, result); this.logger.info(`[InMemoryResultRepository] Result ${result.id} updated successfully.`); return result; } catch (error) { this.logger.error(`[InMemoryResultRepository] Error updating result ${result.id}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } async delete(id: string): Promise { this.logger.debug(`[InMemoryResultRepository] Deleting result: ${id}`); try { if (!await this.exists(id)) { this.logger.warn(`[InMemoryResultRepository] Result with ID ${id} not found for deletion. Throwing error.`); throw new Error(`Result with ID ${id} not found`); } this.results.delete(id); this.logger.info(`[InMemoryResultRepository] Result ${id} deleted successfully.`); } catch (error) { this.logger.error(`[InMemoryResultRepository] Error deleting result ${id}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } async deleteByRaceId(raceId: string): Promise { this.logger.debug(`[InMemoryResultRepository] Deleting results for race id: ${raceId}`); try { const raceResults = Array.from(this.results.values()).filter( result => result.raceId.toString() === raceId ); raceResults.forEach(result => { this.results.delete(result.id); }); this.logger.info(`[InMemoryResultRepository] Deleted ${raceResults.length} results for race id: ${raceId}.`); } catch (error) { this.logger.error(`[InMemoryResultRepository] Error deleting results for race id ${raceId}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } async exists(id: string): Promise { this.logger.debug(`[InMemoryResultRepository] Checking existence of result with id: ${id}`); try { const exists = this.results.has(id); this.logger.debug(`[InMemoryResultRepository] Result ${id} exists: ${exists}.`); return exists; } catch (error) { this.logger.error(`[InMemoryResultRepository] Error checking existence of result with id ${id}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } async existsByRaceId(raceId: string): Promise { this.logger.debug(`[InMemoryResultRepository] Checking existence of results for race id: ${raceId}`); try { const exists = Array.from(this.results.values()).some( result => result.raceId.toString() === raceId ); this.logger.debug(`[InMemoryResultRepository] Results for race ${raceId} exist: ${exists}.`); return exists; } catch (error) { this.logger.error(`[InMemoryResultRepository] Error checking existence of results for race id ${raceId}:`, error instanceof Error ? error : new Error(String(error))); throw error; } } /** * Utility method to generate a new UUID */ static generateId(): string { return uuidv4(); } }