/** * Application Layer: Entity to DTO Mappers * * Transforms domain entities to plain objects for crossing architectural boundaries. * These mappers handle the Server Component -> Client Component boundary in Next.js 15. */ import { Driver } from '../../domain/entities/Driver'; import { League } from '../../domain/entities/League'; import { Race } from '../../domain/entities/Race'; import { Result } from '../../domain/entities/Result'; import { Standing } from '../../domain/entities/Standing'; import type { DriverDTO } from '../dto/DriverDTO'; import type { LeagueDTO } from '../dto/LeagueDTO'; import type { RaceDTO } from '../dto/RaceDTO'; import type { ResultDTO } from '../dto/ResultDTO'; import type { StandingDTO } from '../dto/StandingDTO'; export class EntityMappers { static toDriverDTO(driver: Driver | null): DriverDTO | null { if (!driver) return null; return { id: driver.id, iracingId: driver.iracingId, name: driver.name, country: driver.country, bio: driver.bio ?? '', joinedAt: driver.joinedAt.toISOString(), }; } static toLeagueDTO(league: League | null): LeagueDTO | null { if (!league) return null; const socialLinks = league.socialLinks !== undefined ? { ...(league.socialLinks.discordUrl !== undefined ? { discordUrl: league.socialLinks.discordUrl } : {}), ...(league.socialLinks.youtubeUrl !== undefined ? { youtubeUrl: league.socialLinks.youtubeUrl } : {}), ...(league.socialLinks.websiteUrl !== undefined ? { websiteUrl: league.socialLinks.websiteUrl } : {}), } : undefined; return { id: league.id, name: league.name, description: league.description, ownerId: league.ownerId, settings: league.settings, createdAt: league.createdAt.toISOString(), ...(socialLinks !== undefined ? { socialLinks } : {}), }; } static toLeagueDTOs(leagues: League[]): LeagueDTO[] { return leagues.map((league) => { const socialLinks = league.socialLinks !== undefined ? { ...(league.socialLinks.discordUrl !== undefined ? { discordUrl: league.socialLinks.discordUrl } : {}), ...(league.socialLinks.youtubeUrl !== undefined ? { youtubeUrl: league.socialLinks.youtubeUrl } : {}), ...(league.socialLinks.websiteUrl !== undefined ? { websiteUrl: league.socialLinks.websiteUrl } : {}), } : undefined; return { id: league.id, name: league.name, description: league.description, ownerId: league.ownerId, settings: league.settings, createdAt: league.createdAt.toISOString(), ...(socialLinks !== undefined ? { socialLinks } : {}), }; }); } static toRaceDTO(race: Race | null): RaceDTO | null { if (!race) return null; return { id: race.id, leagueId: race.leagueId, scheduledAt: race.scheduledAt.toISOString(), track: race.track, trackId: race.trackId ?? '', car: race.car, carId: race.carId ?? '', sessionType: race.sessionType, status: race.status, ...(race.strengthOfField !== undefined ? { strengthOfField: race.strengthOfField } : {}), ...(race.registeredCount !== undefined ? { registeredCount: race.registeredCount } : {}), ...(race.maxParticipants !== undefined ? { maxParticipants: race.maxParticipants } : {}), }; } static toRaceDTOs(races: Race[]): RaceDTO[] { return races.map((race) => ({ id: race.id, leagueId: race.leagueId, scheduledAt: race.scheduledAt.toISOString(), track: race.track, trackId: race.trackId ?? '', car: race.car, carId: race.carId ?? '', sessionType: race.sessionType, status: race.status, ...(race.strengthOfField !== undefined ? { strengthOfField: race.strengthOfField } : {}), ...(race.registeredCount !== undefined ? { registeredCount: race.registeredCount } : {}), ...(race.maxParticipants !== undefined ? { maxParticipants: race.maxParticipants } : {}), })); } static toResultDTO(result: Result | null): ResultDTO | null { if (!result) return null; return { id: result.id, raceId: result.raceId, driverId: result.driverId, position: result.position, fastestLap: result.fastestLap, incidents: result.incidents, startPosition: result.startPosition, }; } static toResultDTOs(results: Result[]): ResultDTO[] { return results.map(result => ({ id: result.id, raceId: result.raceId, driverId: result.driverId, position: result.position, fastestLap: result.fastestLap, incidents: result.incidents, startPosition: result.startPosition, })); } static toStandingDTO(standing: Standing | null): StandingDTO | null { if (!standing) return null; return { leagueId: standing.leagueId, driverId: standing.driverId, points: standing.points, wins: standing.wins, position: standing.position, racesCompleted: standing.racesCompleted, }; } static toStandingDTOs(standings: Standing[]): StandingDTO[] { return standings.map(standing => ({ leagueId: standing.leagueId, driverId: standing.driverId, points: standing.points, wins: standing.wins, position: standing.position, racesCompleted: standing.racesCompleted, })); } }