/** * Infrastructure Adapter: InMemoryLeagueMembershipRepository * * In-memory implementation of ILeagueMembershipRepository. * Stores memberships and join requests in maps keyed by league. */ import type { LeagueMembership, JoinRequest, } from '@gridpilot/racing/domain/entities/LeagueMembership'; import type { ILeagueMembershipRepository } from '@gridpilot/racing/domain/repositories/ILeagueMembershipRepository'; import type { ILogger } from '@gridpilot/shared/logging/ILogger'; export class InMemoryLeagueMembershipRepository implements ILeagueMembershipRepository { private membershipsByLeague: Map; private joinRequestsByLeague: Map; private readonly logger: ILogger; constructor(logger: ILogger, seedMemberships?: LeagueMembership[], seedJoinRequests?: JoinRequest[]) { this.logger = logger; this.logger.info('InMemoryLeagueMembershipRepository initialized.'); this.membershipsByLeague = new Map(); this.joinRequestsByLeague = new Map(); if (seedMemberships) { seedMemberships.forEach((membership) => { const list = this.membershipsByLeague.get(membership.leagueId) ?? []; list.push(membership); this.membershipsByLeague.set(membership.leagueId, list); this.logger.debug(`Seeded membership for league ${membership.leagueId}, driver ${membership.driverId}.`); }); } if (seedJoinRequests) { seedJoinRequests.forEach((request) => { const list = this.joinRequestsByLeague.get(request.leagueId) ?? []; list.push(request); this.joinRequestsByLeague.set(request.leagueId, list); this.logger.debug(`Seeded join request for league ${request.leagueId}, driver ${request.driverId}.`); }); } } async getMembership(leagueId: string, driverId: string): Promise { this.logger.debug(`Getting membership for league: ${leagueId}, driver: ${driverId}`); try { const list = this.membershipsByLeague.get(leagueId); if (!list) { this.logger.warn(`No membership list found for league: ${leagueId}.`); return null; } const membership = list.find((m) => m.driverId === driverId) ?? null; if (membership) { this.logger.info(`Found membership for league: ${leagueId}, driver: ${driverId}.`); } else { this.logger.warn(`Membership not found for league: ${leagueId}, driver: ${driverId}.`); } return membership; } catch (error) { this.logger.error(`Error getting membership for league ${leagueId}, driver ${driverId}:`, error); throw error; } } async getLeagueMembers(leagueId: string): Promise { this.logger.debug(`Getting league members for league: ${leagueId}`); try { const members = [...(this.membershipsByLeague.get(leagueId) ?? [])]; this.logger.info(`Found ${members.length} members for league: ${leagueId}.`); return members; } catch (error) { this.logger.error(`Error getting league members for league ${leagueId}:`, error); throw error; } } async getJoinRequests(leagueId: string): Promise { this.logger.debug(`Getting join requests for league: ${leagueId}`); try { const requests = [...(this.joinRequestsByLeague.get(leagueId) ?? [])]; this.logger.info(`Found ${requests.length} join requests for league: ${leagueId}.`); return requests; } catch (error) { this.logger.error(`Error getting join requests for league ${leagueId}:`, error); throw error; } } async saveMembership(membership: LeagueMembership): Promise { this.logger.debug(`Saving membership for league: ${membership.leagueId}, driver: ${membership.driverId}`); try { const list = this.membershipsByLeague.get(membership.leagueId) ?? []; const existingIndex = list.findIndex( (m) => m.leagueId === membership.leagueId && m.driverId === membership.driverId, ); if (existingIndex >= 0) { list[existingIndex] = membership; this.logger.info(`Updated existing membership for league: ${membership.leagueId}, driver: ${membership.driverId}.`); } else { list.push(membership); this.logger.info(`Created new membership for league: ${membership.leagueId}, driver: ${membership.driverId}.`); } this.membershipsByLeague.set(membership.leagueId, list); return membership; } catch (error) { this.logger.error(`Error saving membership for league ${membership.leagueId}, driver ${membership.driverId}:`, error); throw error; } } async removeMembership(leagueId: string, driverId: string): Promise { this.logger.debug(`Removing membership for league: ${leagueId}, driver: ${driverId}`); try { const list = this.membershipsByLeague.get(leagueId); if (!list) { this.logger.warn(`No membership list found for league: ${leagueId}. Cannot remove.`); return; } const next = list.filter((m) => m.driverId !== driverId); if (next.length < list.length) { this.membershipsByLeague.set(leagueId, next); this.logger.info(`Removed membership for league: ${leagueId}, driver: ${driverId}.`); } else { this.logger.warn(`Membership not found for league: ${leagueId}, driver: ${driverId}. Cannot remove.`); } } catch (error) { this.logger.error(`Error removing membership for league ${leagueId}, driver ${driverId}:`, error); throw error; } } async saveJoinRequest(request: JoinRequest): Promise { this.logger.debug(`Saving join request for league: ${request.leagueId}, driver: ${request.driverId}, id: ${request.id}`); try { const list = this.joinRequestsByLeague.get(request.leagueId) ?? []; const existingIndex = list.findIndex((r) => r.id === request.id); if (existingIndex >= 0) { list[existingIndex] = request; this.logger.info(`Updated existing join request: ${request.id}.`); } else { list.push(request); this.logger.info(`Created new join request: ${request.id}.`); } this.joinRequestsByLeague.set(request.leagueId, list); return request; } catch (error) { this.logger.error(`Error saving join request ${request.id}:`, error); throw error; } } async removeJoinRequest(requestId: string): Promise { this.logger.debug(`Removing join request with ID: ${requestId}`); try { let removed = false; for (const [leagueId, requests] of this.joinRequestsByLeague.entries()) { const next = requests.filter((r) => r.id !== requestId); if (next.length !== requests.length) { this.joinRequestsByLeague.set(leagueId, next); removed = true; this.logger.info(`Removed join request ${requestId} from league ${leagueId}.`); break; } } if (!removed) { this.logger.warn(`Join request with ID ${requestId} not found for removal.`); } } catch (error) { this.logger.error(`Error removing join request ${requestId}:`, error); throw error; } } }