Files
gridpilot.gg/core/racing/application/mappers/EntityMappers.ts
2025-12-16 15:42:38 +01:00

207 lines
6.3 KiB
TypeScript

/**
* 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;
const sessionTypeMap = {
practice: 'practice' as const,
qualifying: 'qualifying' as const,
q1: 'qualifying' as const,
q2: 'qualifying' as const,
q3: 'qualifying' as const,
sprint: 'race' as const,
main: 'race' as const,
timeTrial: 'practice' as const,
};
return {
id: race.id,
leagueId: race.leagueId,
scheduledAt: race.scheduledAt.toISOString(),
track: race.track,
trackId: race.trackId ?? '',
car: race.car,
carId: race.carId ?? '',
sessionType: sessionTypeMap[race.sessionType.value],
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[] {
const sessionTypeMap = {
practice: 'practice' as const,
qualifying: 'qualifying' as const,
q1: 'qualifying' as const,
q2: 'qualifying' as const,
q3: 'qualifying' as const,
sprint: 'race' as const,
main: 'race' as const,
timeTrial: 'practice' as const,
};
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: sessionTypeMap[race.sessionType.value],
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,
}));
}
}