Files
gridpilot.gg/apps/api/src/domain/driver/DriverService.ts
2026-01-17 22:55:03 +01:00

210 lines
9.2 KiB
TypeScript

import { Result } from '@core/shared/domain/Result';
import { Inject, Injectable } from '@nestjs/common';
import { CompleteOnboardingInputDTO } from './dtos/CompleteOnboardingInputDTO';
import { CompleteOnboardingOutputDTO } from './dtos/CompleteOnboardingOutputDTO';
import { DriverRegistrationStatusDTO } from './dtos/DriverRegistrationStatusDTO';
import { DriversLeaderboardDTO } from './dtos/DriversLeaderboardDTO';
import { DriverStatsDTO } from './dtos/DriverStatsDTO';
import { GetDriverLiveriesOutputDTO } from './dtos/GetDriverLiveriesOutputDTO';
import { GetDriverOutputDTO } from './dtos/GetDriverOutputDTO';
import { GetDriverProfileOutputDTO } from './dtos/GetDriverProfileOutputDTO';
import { GetDriverRegistrationStatusQueryDTO } from './dtos/GetDriverRegistrationStatusQueryDTO';
// Use cases
import { CompleteDriverOnboardingUseCase } from '@core/racing/application/use-cases/CompleteDriverOnboardingUseCase';
import { GetDriverLiveriesUseCase } from '@core/racing/application/use-cases/GetDriverLiveriesUseCase';
import { GetDriversLeaderboardUseCase } from '@core/racing/application/use-cases/GetDriversLeaderboardUseCase';
import { GetDriverUseCase } from '@core/racing/application/use-cases/GetDriverUseCase';
import { GetProfileOverviewUseCase } from '@core/racing/application/use-cases/GetProfileOverviewUseCase';
import { GetTotalDriversUseCase } from '@core/racing/application/use-cases/GetTotalDriversUseCase';
import { IsDriverRegisteredForRaceUseCase } from '@core/racing/application/use-cases/IsDriverRegisteredForRaceUseCase';
import { UpdateDriverProfileUseCase, type UpdateDriverProfileInput } from '@core/racing/application/use-cases/UpdateDriverProfileUseCase';
// Presenters
import { CompleteOnboardingPresenter } from './presenters/CompleteOnboardingPresenter';
import { DriverPresenter } from './presenters/DriverPresenter';
import { DriverProfilePresenter } from './presenters/DriverProfilePresenter';
import { DriverRegistrationStatusPresenter } from './presenters/DriverRegistrationStatusPresenter';
import { DriversLeaderboardPresenter } from './presenters/DriversLeaderboardPresenter';
import { DriverStatsPresenter } from './presenters/DriverStatsPresenter';
import { GetDriverLiveriesPresenter } from './presenters/GetDriverLiveriesPresenter';
// Tokens
import type { Logger } from '@core/shared/domain/Logger';
import {
COMPLETE_DRIVER_ONBOARDING_USE_CASE_TOKEN,
GET_DRIVER_LIVERIES_USE_CASE_TOKEN,
GET_DRIVER_USE_CASE_TOKEN,
GET_DRIVERS_LEADERBOARD_USE_CASE_TOKEN,
GET_PROFILE_OVERVIEW_USE_CASE_TOKEN,
GET_TOTAL_DRIVERS_USE_CASE_TOKEN,
IS_DRIVER_REGISTERED_FOR_RACE_USE_CASE_TOKEN,
LOGGER_TOKEN,
UPDATE_DRIVER_PROFILE_USE_CASE_TOKEN,
} from './DriverTokens';
@Injectable()
export class DriverService {
constructor(
@Inject(GET_DRIVERS_LEADERBOARD_USE_CASE_TOKEN)
private readonly getDriversLeaderboardUseCase: GetDriversLeaderboardUseCase,
@Inject(GET_TOTAL_DRIVERS_USE_CASE_TOKEN)
private readonly getTotalDriversUseCase: GetTotalDriversUseCase,
@Inject(GET_DRIVER_LIVERIES_USE_CASE_TOKEN)
private readonly getDriverLiveriesUseCase: GetDriverLiveriesUseCase,
@Inject(COMPLETE_DRIVER_ONBOARDING_USE_CASE_TOKEN)
private readonly completeDriverOnboardingUseCase: CompleteDriverOnboardingUseCase,
@Inject(IS_DRIVER_REGISTERED_FOR_RACE_USE_CASE_TOKEN)
private readonly isDriverRegisteredForRaceUseCase: IsDriverRegisteredForRaceUseCase,
@Inject(UPDATE_DRIVER_PROFILE_USE_CASE_TOKEN)
private readonly updateDriverProfileUseCase: UpdateDriverProfileUseCase,
@Inject(GET_PROFILE_OVERVIEW_USE_CASE_TOKEN)
private readonly getProfileOverviewUseCase: GetProfileOverviewUseCase,
@Inject(GET_DRIVER_USE_CASE_TOKEN)
private readonly getDriverUseCase: GetDriverUseCase,
@Inject(LOGGER_TOKEN)
private readonly logger: Logger,
// Injected presenters (optional for module test compatibility)
private readonly driversLeaderboardPresenter?: DriversLeaderboardPresenter,
private readonly driverStatsPresenter?: DriverStatsPresenter,
private readonly completeOnboardingPresenter?: CompleteOnboardingPresenter,
private readonly driverRegistrationStatusPresenter?: DriverRegistrationStatusPresenter,
private readonly driverPresenter?: DriverPresenter,
private readonly driverProfilePresenter?: DriverProfilePresenter,
private readonly getDriverLiveriesPresenter?: GetDriverLiveriesPresenter,
) {
// Presenters are configured by providers, no need to configure here
}
async getDriversLeaderboard(): Promise<DriversLeaderboardDTO> {
this.logger.debug('[DriverService] Fetching drivers leaderboard.');
const result = await this.getDriversLeaderboardUseCase.execute({});
if (result.isErr()) {
throw new Error(result.unwrapErr().details.message);
}
await this.driversLeaderboardPresenter!.present(result.unwrap());
return this.driversLeaderboardPresenter!.getResponseModel();
}
async getTotalDrivers(): Promise<DriverStatsDTO> {
this.logger.debug('[DriverService] Fetching total drivers count.');
const result = await this.getTotalDriversUseCase.execute({});
if (result.isErr()) {
throw new Error(result.unwrapErr().details.message);
}
await this.driverStatsPresenter!.present(result.unwrap());
return this.driverStatsPresenter!.getResponseModel();
}
async completeOnboarding(
userId: string,
input: CompleteOnboardingInputDTO,
): Promise<CompleteOnboardingOutputDTO> {
this.logger.debug('Completing onboarding for user:', userId);
const result = await this.completeDriverOnboardingUseCase.execute({
userId,
firstName: input.firstName,
lastName: input.lastName,
displayName: input.displayName,
country: input.country,
...(input.bio !== undefined ? { bio: input.bio } : {}),
});
if (result.isErr()) {
throw new Error(result.unwrapErr().details.message);
}
await this.completeOnboardingPresenter!.present(result.unwrap());
return this.completeOnboardingPresenter!.getResponseModel();
}
async getDriverRegistrationStatus(
query: GetDriverRegistrationStatusQueryDTO,
): Promise<DriverRegistrationStatusDTO> {
this.logger.debug('Checking driver registration status:', query);
const result = await this.isDriverRegisteredForRaceUseCase.execute({
raceId: query.raceId,
driverId: query.driverId,
});
if (result.isErr()) {
throw new Error(result.unwrapErr().details.message);
}
await this.driverRegistrationStatusPresenter!.present(result.unwrap());
return this.driverRegistrationStatusPresenter!.getResponseModel();
}
async getCurrentDriver(userId: string): Promise<GetDriverOutputDTO | null> {
this.logger.debug(`[DriverService] Fetching current driver for userId: ${userId}`);
const result = await this.getDriverUseCase.execute({ driverId: userId });
if (result.isErr()) {
throw new Error(result.unwrapErr().message);
}
await this.driverPresenter!.present(Result.ok(result.unwrap()));
return this.driverPresenter!.getResponseModel();
}
async updateDriverProfile(
driverId: string,
bio?: string,
country?: string,
): Promise<GetDriverOutputDTO | null> {
this.logger.debug(`[DriverService] Updating driver profile for driverId: ${driverId}`);
const input: UpdateDriverProfileInput = { driverId };
if (bio !== undefined) input.bio = bio;
if (country !== undefined) input.country = country;
await this.updateDriverProfileUseCase.execute(input);
// Get the updated driver and present it
const result = await this.getDriverUseCase.execute({ driverId });
if (result.isErr()) {
throw new Error(result.unwrapErr().message);
}
await this.driverPresenter!.present(Result.ok(result.unwrap()));
return this.driverPresenter!.getResponseModel();
}
async getDriver(driverId: string): Promise<GetDriverOutputDTO | null> {
this.logger.debug(`[DriverService] Fetching driver for driverId: ${driverId}`);
const result = await this.getDriverUseCase.execute({ driverId });
if (result.isErr()) {
throw new Error(result.unwrapErr().message);
}
const driver = result.unwrap();
if (!driver) {
return null;
}
await this.driverPresenter!.present(Result.ok(driver));
return this.driverPresenter!.getResponseModel();
}
async getDriverProfile(driverId: string): Promise<GetDriverProfileOutputDTO> {
this.logger.debug(`[DriverService] Fetching driver profile for driverId: ${driverId}`);
const result = await this.getProfileOverviewUseCase.execute({ driverId });
if (result.isErr()) {
throw new Error(result.unwrapErr().details.message);
}
await this.driverProfilePresenter!.present(result.unwrap());
return this.driverProfilePresenter!.getResponseModel();
}
async getDriverLiveries(driverId: string): Promise<GetDriverLiveriesOutputDTO> {
this.logger.debug(`[DriverService] Fetching driver liveries for driverId: ${driverId}`);
const result = await this.getDriverLiveriesUseCase.execute({ driverId });
if (result.isErr()) {
throw new Error(result.unwrapErr().details.message);
}
await this.getDriverLiveriesPresenter!.present(result);
return this.getDriverLiveriesPresenter!.getResponseModel()!;
}
}