refactor use cases
This commit is contained in:
@@ -12,8 +12,6 @@ import type { IRaceRepository } from '@core/racing/domain/repositories/IRaceRepo
|
||||
import type { IResultRepository } from '@core/racing/domain/repositories/IResultRepository';
|
||||
import type { IStandingRepository } from '@core/racing/domain/repositories/IStandingRepository';
|
||||
import type { Logger } from '@core/shared/application/Logger';
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
import { Result } from '@core/shared/application/Result';
|
||||
|
||||
// Import concrete in-memory implementations
|
||||
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
|
||||
@@ -43,29 +41,6 @@ import { RequestProtestDefenseUseCase } from '@core/racing/application/use-cases
|
||||
import { ReviewProtestUseCase } from '@core/racing/application/use-cases/ReviewProtestUseCase';
|
||||
import { WithdrawFromRaceUseCase } from '@core/racing/application/use-cases/WithdrawFromRaceUseCase';
|
||||
|
||||
// Import use case result types
|
||||
import type { GetAllRacesResult } from '@core/racing/application/use-cases/GetAllRacesUseCase';
|
||||
import type { GetTotalRacesResult } from '@core/racing/application/use-cases/GetTotalRacesUseCase';
|
||||
import type { ImportRaceResultsApiResult } from '@core/racing/application/use-cases/ImportRaceResultsApiUseCase';
|
||||
import type { GetRaceDetailResult } from '@core/racing/application/use-cases/GetRaceDetailUseCase';
|
||||
import type { GetRacesPageDataResult } from '@core/racing/application/use-cases/GetRacesPageDataUseCase';
|
||||
import type { GetAllRacesPageDataResult } from '@core/racing/application/use-cases/GetAllRacesPageDataUseCase';
|
||||
import type { GetRaceResultsDetailResult } from '@core/racing/application/use-cases/GetRaceResultsDetailUseCase';
|
||||
import type { GetRaceWithSOFResult } from '@core/racing/application/use-cases/GetRaceWithSOFUseCase';
|
||||
import type { GetRaceProtestsResult } from '@core/racing/application/use-cases/GetRaceProtestsUseCase';
|
||||
import type { GetRacePenaltiesResult } from '@core/racing/application/use-cases/GetRacePenaltiesUseCase';
|
||||
import type { RegisterForRaceResult } from '@core/racing/application/use-cases/RegisterForRaceUseCase';
|
||||
import type { WithdrawFromRaceResult } from '@core/racing/application/use-cases/WithdrawFromRaceUseCase';
|
||||
import type { CancelRaceResult } from '@core/racing/application/use-cases/CancelRaceUseCase';
|
||||
import type { CompleteRaceResult } from '@core/racing/application/use-cases/CompleteRaceUseCase';
|
||||
import type { ReopenRaceResult } from '@core/racing/application/use-cases/ReopenRaceUseCase';
|
||||
import type { ImportRaceResultsResult } from '@core/racing/application/use-cases/ImportRaceResultsUseCase';
|
||||
import type { FileProtestResult } from '@core/racing/application/use-cases/FileProtestUseCase';
|
||||
import type { QuickPenaltyResult } from '@core/racing/application/use-cases/QuickPenaltyUseCase';
|
||||
import type { ApplyPenaltyResult } from '@core/racing/application/use-cases/ApplyPenaltyUseCase';
|
||||
import type { RequestProtestDefenseResult } from '@core/racing/application/use-cases/RequestProtestDefenseUseCase';
|
||||
import type { ReviewProtestResult } from '@core/racing/application/use-cases/ReviewProtestUseCase';
|
||||
|
||||
// Import presenters
|
||||
import { AllRacesPageDataPresenter } from './presenters/AllRacesPageDataPresenter';
|
||||
import { CommandResultPresenter } from './presenters/CommandResultPresenter';
|
||||
@@ -107,183 +82,6 @@ import {
|
||||
|
||||
export * from './RaceTokens';
|
||||
|
||||
// Adapter classes to bridge presenters with UseCaseOutputPort interface
|
||||
class GetAllRacesOutputAdapter implements UseCaseOutputPort<GetAllRacesResult> {
|
||||
constructor(private presenter: GetAllRacesPresenter) {}
|
||||
|
||||
present(result: GetAllRacesResult): void {
|
||||
this.presenter.present(result);
|
||||
}
|
||||
}
|
||||
|
||||
class GetTotalRacesOutputAdapter implements UseCaseOutputPort<GetTotalRacesResult> {
|
||||
constructor(private presenter: GetTotalRacesPresenter) {}
|
||||
|
||||
present(result: GetTotalRacesResult): void {
|
||||
// Wrap the result in a Result.ok() to match presenter expectations
|
||||
const resultWrapper = Result.ok<GetTotalRacesResult, { code: 'REPOSITORY_ERROR'; details: { message: string } }>(result);
|
||||
this.presenter.present(resultWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
class ImportRaceResultsApiOutputAdapter implements UseCaseOutputPort<ImportRaceResultsApiResult> {
|
||||
constructor(private presenter: ImportRaceResultsApiPresenter) {}
|
||||
|
||||
present(result: ImportRaceResultsApiResult): void {
|
||||
const resultWrapper = Result.ok<ImportRaceResultsApiResult, { code: 'REPOSITORY_ERROR'; details: { message: string } }>(result);
|
||||
this.presenter.present(resultWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
class RaceDetailOutputAdapter implements UseCaseOutputPort<GetRaceDetailResult> {
|
||||
constructor(private presenter: RaceDetailPresenter) {}
|
||||
|
||||
present(result: GetRaceDetailResult): void {
|
||||
this.presenter.present(result);
|
||||
}
|
||||
}
|
||||
|
||||
class RacesPageDataOutputAdapter implements UseCaseOutputPort<GetRacesPageDataResult> {
|
||||
constructor(private presenter: RacesPageDataPresenter) {}
|
||||
|
||||
present(result: GetRacesPageDataResult): void {
|
||||
const resultWrapper = Result.ok<GetRacesPageDataResult, { code: 'REPOSITORY_ERROR'; details: { message: string } }>(result);
|
||||
this.presenter.present(resultWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
class AllRacesPageDataOutputAdapter implements UseCaseOutputPort<GetAllRacesPageDataResult> {
|
||||
constructor(private presenter: AllRacesPageDataPresenter) {}
|
||||
|
||||
present(result: GetAllRacesPageDataResult): void {
|
||||
const resultWrapper = Result.ok<GetAllRacesPageDataResult, { code: 'REPOSITORY_ERROR'; details: { message: string } }>(result);
|
||||
this.presenter.present(resultWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
class RaceResultsDetailOutputAdapter implements UseCaseOutputPort<GetRaceResultsDetailResult> {
|
||||
constructor(private presenter: RaceResultsDetailPresenter) {}
|
||||
|
||||
present(result: GetRaceResultsDetailResult): void {
|
||||
this.presenter.present(result);
|
||||
}
|
||||
}
|
||||
|
||||
class RaceWithSOFOutputAdapter implements UseCaseOutputPort<GetRaceWithSOFResult> {
|
||||
constructor(private presenter: RaceWithSOFPresenter) {}
|
||||
|
||||
present(result: GetRaceWithSOFResult): void {
|
||||
const resultWrapper = Result.ok<GetRaceWithSOFResult, { code: 'RACE_NOT_FOUND' | 'REPOSITORY_ERROR'; details: { message: string } }>(result);
|
||||
this.presenter.present(resultWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
class RaceProtestsOutputAdapter implements UseCaseOutputPort<GetRaceProtestsResult> {
|
||||
constructor(private presenter: RaceProtestsPresenter) {}
|
||||
|
||||
present(result: GetRaceProtestsResult): void {
|
||||
const resultWrapper = Result.ok<GetRaceProtestsResult, { code: 'REPOSITORY_ERROR'; details: { message: string } }>(result);
|
||||
this.presenter.present(resultWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
class RacePenaltiesOutputAdapter implements UseCaseOutputPort<GetRacePenaltiesResult> {
|
||||
constructor(private presenter: RacePenaltiesPresenter) {}
|
||||
|
||||
present(result: GetRacePenaltiesResult): void {
|
||||
const resultWrapper = Result.ok<GetRacePenaltiesResult, { code: 'REPOSITORY_ERROR'; details: { message: string } }>(result);
|
||||
this.presenter.present(resultWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
class RegisterForRaceOutputAdapter implements UseCaseOutputPort<RegisterForRaceResult> {
|
||||
constructor(private presenter: CommandResultPresenter) {}
|
||||
|
||||
present(): void {
|
||||
this.presenter.presentSuccess('Race registered successfully');
|
||||
}
|
||||
}
|
||||
|
||||
class WithdrawFromRaceOutputAdapter implements UseCaseOutputPort<WithdrawFromRaceResult> {
|
||||
constructor(private presenter: CommandResultPresenter) {}
|
||||
|
||||
present(): void {
|
||||
this.presenter.presentSuccess('Race withdrawal successful');
|
||||
}
|
||||
}
|
||||
|
||||
class CancelRaceOutputAdapter implements UseCaseOutputPort<CancelRaceResult> {
|
||||
constructor(private presenter: CommandResultPresenter) {}
|
||||
|
||||
present(): void {
|
||||
this.presenter.presentSuccess('Race cancelled successfully');
|
||||
}
|
||||
}
|
||||
|
||||
class CompleteRaceOutputAdapter implements UseCaseOutputPort<CompleteRaceResult> {
|
||||
constructor(private presenter: CommandResultPresenter) {}
|
||||
|
||||
present(): void {
|
||||
this.presenter.presentSuccess('Race completed successfully');
|
||||
}
|
||||
}
|
||||
|
||||
class ReopenRaceOutputAdapter implements UseCaseOutputPort<ReopenRaceResult> {
|
||||
constructor(private presenter: CommandResultPresenter) {}
|
||||
|
||||
present(): void {
|
||||
this.presenter.presentSuccess('Race reopened successfully');
|
||||
}
|
||||
}
|
||||
|
||||
class ImportRaceResultsOutputAdapter implements UseCaseOutputPort<ImportRaceResultsResult> {
|
||||
constructor(private presenter: CommandResultPresenter) {}
|
||||
|
||||
present(): void {
|
||||
this.presenter.presentSuccess('Race results imported successfully');
|
||||
}
|
||||
}
|
||||
|
||||
class FileProtestOutputAdapter implements UseCaseOutputPort<FileProtestResult> {
|
||||
constructor(private presenter: CommandResultPresenter) {}
|
||||
|
||||
present(): void {
|
||||
this.presenter.presentSuccess('Protest filed successfully');
|
||||
}
|
||||
}
|
||||
|
||||
class QuickPenaltyOutputAdapter implements UseCaseOutputPort<QuickPenaltyResult> {
|
||||
constructor(private presenter: CommandResultPresenter) {}
|
||||
|
||||
present(): void {
|
||||
this.presenter.presentSuccess('Penalty applied successfully');
|
||||
}
|
||||
}
|
||||
|
||||
class ApplyPenaltyOutputAdapter implements UseCaseOutputPort<ApplyPenaltyResult> {
|
||||
constructor(private presenter: CommandResultPresenter) {}
|
||||
|
||||
present(): void {
|
||||
this.presenter.presentSuccess('Penalty applied successfully');
|
||||
}
|
||||
}
|
||||
|
||||
class RequestProtestDefenseOutputAdapter implements UseCaseOutputPort<RequestProtestDefenseResult> {
|
||||
constructor(private presenter: CommandResultPresenter) {}
|
||||
|
||||
present(): void {
|
||||
this.presenter.presentSuccess('Defense request sent successfully');
|
||||
}
|
||||
}
|
||||
|
||||
class ReviewProtestOutputAdapter implements UseCaseOutputPort<ReviewProtestResult> {
|
||||
constructor(private presenter: CommandResultPresenter) {}
|
||||
|
||||
present(): void {
|
||||
this.presenter.presentSuccess('Protest reviewed successfully');
|
||||
}
|
||||
}
|
||||
|
||||
export const RaceProviders: Provider[] = [
|
||||
{
|
||||
provide: DRIVER_RATING_PROVIDER_TOKEN,
|
||||
@@ -354,24 +152,19 @@ export const RaceProviders: Provider[] = [
|
||||
raceRepo: IRaceRepository,
|
||||
leagueRepo: ILeagueRepository,
|
||||
logger: Logger,
|
||||
presenter: GetAllRacesPresenter,
|
||||
) => {
|
||||
const useCase = new GetAllRacesUseCase(raceRepo, leagueRepo, logger);
|
||||
useCase.setOutput(new GetAllRacesOutputAdapter(presenter));
|
||||
return useCase;
|
||||
return new GetAllRacesUseCase(raceRepo, leagueRepo, logger);
|
||||
},
|
||||
inject: [RACE_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN, LOGGER_TOKEN, GET_ALL_RACES_PRESENTER_TOKEN],
|
||||
inject: [RACE_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetTotalRacesUseCase,
|
||||
useFactory: (
|
||||
raceRepo: IRaceRepository,
|
||||
logger: Logger,
|
||||
presenter: GetTotalRacesPresenter,
|
||||
) => {
|
||||
return new GetTotalRacesUseCase(raceRepo, logger, new GetTotalRacesOutputAdapter(presenter));
|
||||
return new GetTotalRacesUseCase(raceRepo);
|
||||
},
|
||||
inject: [RACE_REPOSITORY_TOKEN, LOGGER_TOKEN, GET_TOTAL_RACES_PRESENTER_TOKEN],
|
||||
inject: [RACE_REPOSITORY_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: ImportRaceResultsApiUseCase,
|
||||
@@ -382,7 +175,6 @@ export const RaceProviders: Provider[] = [
|
||||
driverRepo: IDriverRepository,
|
||||
standingRepo: IStandingRepository,
|
||||
logger: Logger,
|
||||
presenter: ImportRaceResultsApiPresenter,
|
||||
) => {
|
||||
return new ImportRaceResultsApiUseCase(
|
||||
raceRepo,
|
||||
@@ -391,7 +183,6 @@ export const RaceProviders: Provider[] = [
|
||||
driverRepo,
|
||||
standingRepo,
|
||||
logger,
|
||||
new ImportRaceResultsApiOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [
|
||||
@@ -401,7 +192,6 @@ export const RaceProviders: Provider[] = [
|
||||
DRIVER_REPOSITORY_TOKEN,
|
||||
STANDING_REPOSITORY_TOKEN,
|
||||
LOGGER_TOKEN,
|
||||
IMPORT_RACE_RESULTS_API_PRESENTER_TOKEN,
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -413,7 +203,6 @@ export const RaceProviders: Provider[] = [
|
||||
raceRegRepo: IRaceRegistrationRepository,
|
||||
resultRepo: IResultRepository,
|
||||
leagueMembershipRepo: ILeagueMembershipRepository,
|
||||
presenter: RaceDetailPresenter,
|
||||
) => {
|
||||
return new GetRaceDetailUseCase(
|
||||
raceRepo,
|
||||
@@ -422,7 +211,6 @@ export const RaceProviders: Provider[] = [
|
||||
raceRegRepo,
|
||||
resultRepo,
|
||||
leagueMembershipRepo,
|
||||
new RaceDetailOutputAdapter(presenter),
|
||||
);
|
||||
},
|
||||
inject: [
|
||||
@@ -432,7 +220,6 @@ export const RaceProviders: Provider[] = [
|
||||
RACE_REGISTRATION_REPOSITORY_TOKEN,
|
||||
RESULT_REPOSITORY_TOKEN,
|
||||
LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
|
||||
RACE_DETAIL_PRESENTER_TOKEN,
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -441,16 +228,14 @@ export const RaceProviders: Provider[] = [
|
||||
raceRepo: IRaceRepository,
|
||||
leagueRepo: ILeagueRepository,
|
||||
logger: Logger,
|
||||
presenter: RacesPageDataPresenter,
|
||||
) => {
|
||||
return new GetRacesPageDataUseCase(
|
||||
raceRepo,
|
||||
leagueRepo,
|
||||
logger,
|
||||
new RacesPageDataOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [RACE_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN, LOGGER_TOKEN, RACES_PAGE_DATA_PRESENTER_TOKEN],
|
||||
inject: [RACE_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetAllRacesPageDataUseCase,
|
||||
@@ -458,16 +243,14 @@ export const RaceProviders: Provider[] = [
|
||||
raceRepo: IRaceRepository,
|
||||
leagueRepo: ILeagueRepository,
|
||||
logger: Logger,
|
||||
presenter: AllRacesPageDataPresenter,
|
||||
) => {
|
||||
return new GetAllRacesPageDataUseCase(
|
||||
raceRepo,
|
||||
leagueRepo,
|
||||
logger,
|
||||
new AllRacesPageDataOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [RACE_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN, LOGGER_TOKEN, ALL_RACES_PAGE_DATA_PRESENTER_TOKEN],
|
||||
inject: [RACE_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetRaceResultsDetailUseCase,
|
||||
@@ -477,7 +260,6 @@ export const RaceProviders: Provider[] = [
|
||||
resultRepo: IResultRepository,
|
||||
driverRepo: IDriverRepository,
|
||||
penaltyRepo: IPenaltyRepository,
|
||||
presenter: RaceResultsDetailPresenter,
|
||||
) => {
|
||||
return new GetRaceResultsDetailUseCase(
|
||||
raceRepo,
|
||||
@@ -485,7 +267,6 @@ export const RaceProviders: Provider[] = [
|
||||
resultRepo,
|
||||
driverRepo,
|
||||
penaltyRepo,
|
||||
new RaceResultsDetailOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [
|
||||
@@ -494,7 +275,6 @@ export const RaceProviders: Provider[] = [
|
||||
RESULT_REPOSITORY_TOKEN,
|
||||
DRIVER_REPOSITORY_TOKEN,
|
||||
PENALTY_REPOSITORY_TOKEN,
|
||||
RACE_RESULTS_DETAIL_PRESENTER_TOKEN,
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -504,7 +284,6 @@ export const RaceProviders: Provider[] = [
|
||||
raceRegRepo: IRaceRegistrationRepository,
|
||||
resultRepo: IResultRepository,
|
||||
driverRatingProvider: DriverRatingProvider,
|
||||
presenter: RaceWithSOFPresenter,
|
||||
) => {
|
||||
return new GetRaceWithSOFUseCase(
|
||||
raceRepo,
|
||||
@@ -514,7 +293,6 @@ export const RaceProviders: Provider[] = [
|
||||
const rating = driverRatingProvider.getRating(input.driverId);
|
||||
return { rating };
|
||||
},
|
||||
new RaceWithSOFOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [
|
||||
@@ -522,7 +300,6 @@ export const RaceProviders: Provider[] = [
|
||||
RACE_REGISTRATION_REPOSITORY_TOKEN,
|
||||
RESULT_REPOSITORY_TOKEN,
|
||||
DRIVER_RATING_PROVIDER_TOKEN,
|
||||
RACE_WITH_SOF_PRESENTER_TOKEN,
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -530,30 +307,26 @@ export const RaceProviders: Provider[] = [
|
||||
useFactory: (
|
||||
protestRepo: IProtestRepository,
|
||||
driverRepo: IDriverRepository,
|
||||
presenter: RaceProtestsPresenter,
|
||||
) => {
|
||||
return new GetRaceProtestsUseCase(
|
||||
protestRepo,
|
||||
driverRepo,
|
||||
new RaceProtestsOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [PROTEST_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN, RACE_PROTESTS_PRESENTER_TOKEN],
|
||||
inject: [PROTEST_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetRacePenaltiesUseCase,
|
||||
useFactory: (
|
||||
penaltyRepo: IPenaltyRepository,
|
||||
driverRepo: IDriverRepository,
|
||||
presenter: RacePenaltiesPresenter,
|
||||
) => {
|
||||
return new GetRacePenaltiesUseCase(
|
||||
penaltyRepo,
|
||||
driverRepo,
|
||||
new RacePenaltiesOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [PENALTY_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN, RACE_PENALTIES_PRESENTER_TOKEN],
|
||||
inject: [PENALTY_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: RegisterForRaceUseCase,
|
||||
@@ -561,16 +334,14 @@ export const RaceProviders: Provider[] = [
|
||||
raceRegRepo: IRaceRegistrationRepository,
|
||||
leagueMembershipRepo: ILeagueMembershipRepository,
|
||||
logger: Logger,
|
||||
presenter: CommandResultPresenter,
|
||||
) => {
|
||||
return new RegisterForRaceUseCase(
|
||||
raceRegRepo,
|
||||
leagueMembershipRepo,
|
||||
logger,
|
||||
new RegisterForRaceOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [RACE_REGISTRATION_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN, COMMAND_RESULT_PRESENTER_TOKEN],
|
||||
inject: [RACE_REGISTRATION_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: WithdrawFromRaceUseCase,
|
||||
@@ -578,31 +349,27 @@ export const RaceProviders: Provider[] = [
|
||||
raceRepo: IRaceRepository,
|
||||
raceRegRepo: IRaceRegistrationRepository,
|
||||
logger: Logger,
|
||||
presenter: CommandResultPresenter,
|
||||
) => {
|
||||
return new WithdrawFromRaceUseCase(
|
||||
raceRepo,
|
||||
raceRegRepo,
|
||||
logger,
|
||||
new WithdrawFromRaceOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [RACE_REPOSITORY_TOKEN, RACE_REGISTRATION_REPOSITORY_TOKEN, LOGGER_TOKEN, COMMAND_RESULT_PRESENTER_TOKEN],
|
||||
inject: [RACE_REPOSITORY_TOKEN, RACE_REGISTRATION_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: CancelRaceUseCase,
|
||||
useFactory: (
|
||||
raceRepo: IRaceRepository,
|
||||
logger: Logger,
|
||||
presenter: CommandResultPresenter,
|
||||
) => {
|
||||
return new CancelRaceUseCase(
|
||||
raceRepo,
|
||||
logger,
|
||||
new CancelRaceOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [RACE_REPOSITORY_TOKEN, LOGGER_TOKEN, COMMAND_RESULT_PRESENTER_TOKEN],
|
||||
inject: [RACE_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: CompleteRaceUseCase,
|
||||
@@ -612,7 +379,6 @@ export const RaceProviders: Provider[] = [
|
||||
resultRepo: IResultRepository,
|
||||
standingRepo: IStandingRepository,
|
||||
driverRatingProvider: DriverRatingProvider,
|
||||
presenter: CommandResultPresenter,
|
||||
) => {
|
||||
return new CompleteRaceUseCase(
|
||||
raceRepo,
|
||||
@@ -623,7 +389,6 @@ export const RaceProviders: Provider[] = [
|
||||
const rating = driverRatingProvider.getRating(input.driverId);
|
||||
return { rating, ratingChange: null };
|
||||
},
|
||||
new CompleteRaceOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [
|
||||
@@ -632,7 +397,6 @@ export const RaceProviders: Provider[] = [
|
||||
RESULT_REPOSITORY_TOKEN,
|
||||
STANDING_REPOSITORY_TOKEN,
|
||||
DRIVER_RATING_PROVIDER_TOKEN,
|
||||
COMMAND_RESULT_PRESENTER_TOKEN,
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -640,15 +404,13 @@ export const RaceProviders: Provider[] = [
|
||||
useFactory: (
|
||||
raceRepo: IRaceRepository,
|
||||
logger: Logger,
|
||||
presenter: CommandResultPresenter,
|
||||
) => {
|
||||
return new ReopenRaceUseCase(
|
||||
raceRepo,
|
||||
logger,
|
||||
new ReopenRaceOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [RACE_REPOSITORY_TOKEN, LOGGER_TOKEN, COMMAND_RESULT_PRESENTER_TOKEN],
|
||||
inject: [RACE_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: ImportRaceResultsUseCase,
|
||||
@@ -659,7 +421,6 @@ export const RaceProviders: Provider[] = [
|
||||
driverRepo: IDriverRepository,
|
||||
standingRepo: IStandingRepository,
|
||||
logger: Logger,
|
||||
presenter: CommandResultPresenter,
|
||||
) => {
|
||||
return new ImportRaceResultsUseCase(
|
||||
raceRepo,
|
||||
@@ -668,7 +429,6 @@ export const RaceProviders: Provider[] = [
|
||||
driverRepo,
|
||||
standingRepo,
|
||||
logger,
|
||||
new ImportRaceResultsOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [
|
||||
@@ -678,7 +438,6 @@ export const RaceProviders: Provider[] = [
|
||||
DRIVER_REPOSITORY_TOKEN,
|
||||
STANDING_REPOSITORY_TOKEN,
|
||||
LOGGER_TOKEN,
|
||||
COMMAND_RESULT_PRESENTER_TOKEN,
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -687,16 +446,14 @@ export const RaceProviders: Provider[] = [
|
||||
protestRepo: IProtestRepository,
|
||||
raceRepo: IRaceRepository,
|
||||
leagueMembershipRepo: ILeagueMembershipRepository,
|
||||
presenter: CommandResultPresenter,
|
||||
) => {
|
||||
return new FileProtestUseCase(
|
||||
protestRepo,
|
||||
raceRepo,
|
||||
leagueMembershipRepo,
|
||||
new FileProtestOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [PROTEST_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, COMMAND_RESULT_PRESENTER_TOKEN],
|
||||
inject: [PROTEST_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: QuickPenaltyUseCase,
|
||||
@@ -705,17 +462,15 @@ export const RaceProviders: Provider[] = [
|
||||
raceRepo: IRaceRepository,
|
||||
leagueMembershipRepo: ILeagueMembershipRepository,
|
||||
logger: Logger,
|
||||
presenter: CommandResultPresenter,
|
||||
) => {
|
||||
return new QuickPenaltyUseCase(
|
||||
penaltyRepo,
|
||||
raceRepo,
|
||||
leagueMembershipRepo,
|
||||
logger,
|
||||
new QuickPenaltyOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [PENALTY_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN, COMMAND_RESULT_PRESENTER_TOKEN],
|
||||
inject: [PENALTY_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: ApplyPenaltyUseCase,
|
||||
@@ -725,7 +480,6 @@ export const RaceProviders: Provider[] = [
|
||||
raceRepo: IRaceRepository,
|
||||
leagueMembershipRepo: ILeagueMembershipRepository,
|
||||
logger: Logger,
|
||||
presenter: CommandResultPresenter,
|
||||
) => {
|
||||
return new ApplyPenaltyUseCase(
|
||||
penaltyRepo,
|
||||
@@ -733,10 +487,9 @@ export const RaceProviders: Provider[] = [
|
||||
raceRepo,
|
||||
leagueMembershipRepo,
|
||||
logger,
|
||||
new ApplyPenaltyOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [PENALTY_REPOSITORY_TOKEN, PROTEST_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN, COMMAND_RESULT_PRESENTER_TOKEN],
|
||||
inject: [PENALTY_REPOSITORY_TOKEN, PROTEST_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: RequestProtestDefenseUseCase,
|
||||
@@ -745,17 +498,15 @@ export const RaceProviders: Provider[] = [
|
||||
raceRepo: IRaceRepository,
|
||||
leagueMembershipRepo: ILeagueMembershipRepository,
|
||||
logger: Logger,
|
||||
presenter: CommandResultPresenter,
|
||||
) => {
|
||||
return new RequestProtestDefenseUseCase(
|
||||
protestRepo,
|
||||
raceRepo,
|
||||
leagueMembershipRepo,
|
||||
logger,
|
||||
new RequestProtestDefenseOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [PROTEST_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN, COMMAND_RESULT_PRESENTER_TOKEN],
|
||||
inject: [PROTEST_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: ReviewProtestUseCase,
|
||||
@@ -764,16 +515,14 @@ export const RaceProviders: Provider[] = [
|
||||
raceRepo: IRaceRepository,
|
||||
leagueMembershipRepo: ILeagueMembershipRepository,
|
||||
logger: Logger,
|
||||
presenter: CommandResultPresenter,
|
||||
) => {
|
||||
return new ReviewProtestUseCase(
|
||||
protestRepo,
|
||||
raceRepo,
|
||||
leagueMembershipRepo,
|
||||
logger,
|
||||
new ReviewProtestOutputAdapter(presenter)
|
||||
);
|
||||
},
|
||||
inject: [PROTEST_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN, COMMAND_RESULT_PRESENTER_TOKEN],
|
||||
inject: [PROTEST_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
];
|
||||
@@ -1,20 +1,24 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { RaceService } from './RaceService';
|
||||
import { Result } from '@core/shared/application/Result';
|
||||
|
||||
describe('RaceService', () => {
|
||||
it('invokes each use case and returns the corresponding presenter', async () => {
|
||||
const mkUseCase = () => ({ execute: vi.fn(async () => {}) });
|
||||
// Mock use cases to return Result.ok()
|
||||
const mkUseCase = (resultValue: any = { success: true }) => ({
|
||||
execute: vi.fn(async () => Result.ok(resultValue))
|
||||
});
|
||||
|
||||
const getAllRacesUseCase = mkUseCase();
|
||||
const getTotalRacesUseCase = mkUseCase();
|
||||
const importRaceResultsApiUseCase = mkUseCase();
|
||||
const getRaceDetailUseCase = mkUseCase();
|
||||
const getRacesPageDataUseCase = mkUseCase();
|
||||
const getAllRacesPageDataUseCase = mkUseCase();
|
||||
const getRaceResultsDetailUseCase = mkUseCase();
|
||||
const getRaceWithSOFUseCase = mkUseCase();
|
||||
const getRaceProtestsUseCase = mkUseCase();
|
||||
const getRacePenaltiesUseCase = mkUseCase();
|
||||
const getAllRacesUseCase = mkUseCase({ races: [], leagues: [] });
|
||||
const getTotalRacesUseCase = mkUseCase({ totalRaces: 0 });
|
||||
const importRaceResultsApiUseCase = mkUseCase({ success: true, raceId: 'r1', driversProcessed: 0, resultsRecorded: 0, errors: [] });
|
||||
const getRaceDetailUseCase = mkUseCase({ race: null, league: null, drivers: [], isUserRegistered: false, canRegister: false });
|
||||
const getRacesPageDataUseCase = mkUseCase({ races: [] });
|
||||
const getAllRacesPageDataUseCase = mkUseCase({ races: [], filters: { statuses: [], leagues: [] } });
|
||||
const getRaceResultsDetailUseCase = mkUseCase({ race: null, results: [], penalties: [] });
|
||||
const getRaceWithSOFUseCase = mkUseCase({ race: null, strengthOfField: 0, participantCount: 0, registeredCount: 0, maxParticipants: 0 });
|
||||
const getRaceProtestsUseCase = mkUseCase({ protests: [], drivers: [] });
|
||||
const getRacePenaltiesUseCase = mkUseCase({ penalties: [], drivers: [] });
|
||||
const registerForRaceUseCase = mkUseCase();
|
||||
const withdrawFromRaceUseCase = mkUseCase();
|
||||
const cancelRaceUseCase = mkUseCase();
|
||||
@@ -28,17 +32,17 @@ describe('RaceService', () => {
|
||||
|
||||
const logger = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() };
|
||||
|
||||
const getAllRacesPresenter = {} as any;
|
||||
const getTotalRacesPresenter = {} as any;
|
||||
const importRaceResultsApiPresenter = {} as any;
|
||||
const raceDetailPresenter = {} as any;
|
||||
const racesPageDataPresenter = {} as any;
|
||||
const allRacesPageDataPresenter = {} as any;
|
||||
const raceResultsDetailPresenter = {} as any;
|
||||
const raceWithSOFPresenter = {} as any;
|
||||
const raceProtestsPresenter = {} as any;
|
||||
const racePenaltiesPresenter = {} as any;
|
||||
const commandResultPresenter = {} as any;
|
||||
const getAllRacesPresenter = { present: vi.fn() } as any;
|
||||
const getTotalRacesPresenter = { present: vi.fn() } as any;
|
||||
const importRaceResultsApiPresenter = { present: vi.fn() } as any;
|
||||
const raceDetailPresenter = { present: vi.fn() } as any;
|
||||
const racesPageDataPresenter = { present: vi.fn() } as any;
|
||||
const allRacesPageDataPresenter = { present: vi.fn() } as any;
|
||||
const raceResultsDetailPresenter = { present: vi.fn() } as any;
|
||||
const raceWithSOFPresenter = { present: vi.fn() } as any;
|
||||
const raceProtestsPresenter = { present: vi.fn() } as any;
|
||||
const racePenaltiesPresenter = { present: vi.fn() } as any;
|
||||
const commandResultPresenter = { present: vi.fn() } as any;
|
||||
|
||||
const service = new RaceService(
|
||||
getAllRacesUseCase as any,
|
||||
@@ -77,62 +81,81 @@ describe('RaceService', () => {
|
||||
|
||||
expect(await service.getAllRaces()).toBe(getAllRacesPresenter);
|
||||
expect(getAllRacesUseCase.execute).toHaveBeenCalledWith({});
|
||||
expect(getAllRacesPresenter.present).toHaveBeenCalledWith({ races: [], leagues: [] });
|
||||
|
||||
expect(await service.getTotalRaces()).toBe(getTotalRacesPresenter);
|
||||
expect(getTotalRacesUseCase.execute).toHaveBeenCalledWith({});
|
||||
expect(getTotalRacesPresenter.present).toHaveBeenCalledWith({ totalRaces: 0 });
|
||||
|
||||
expect(await service.importRaceResults({ raceId: 'r1', resultsFileContent: 'x' } as any)).toBe(importRaceResultsApiPresenter);
|
||||
expect(importRaceResultsApiUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1', resultsFileContent: 'x' });
|
||||
expect(importRaceResultsApiPresenter.present).toHaveBeenCalledWith({ success: true, raceId: 'r1', driversProcessed: 0, resultsRecorded: 0, errors: [] });
|
||||
|
||||
expect(await service.getRaceDetail({ raceId: 'r1' } as any)).toBe(raceDetailPresenter);
|
||||
expect(getRaceDetailUseCase.execute).toHaveBeenCalled();
|
||||
|
||||
expect(await service.getRacesPageData('l1')).toBe(racesPageDataPresenter);
|
||||
expect(getRacesPageDataUseCase.execute).toHaveBeenCalledWith({ leagueId: 'l1' });
|
||||
expect(racesPageDataPresenter.present).toHaveBeenCalledWith({ races: [] });
|
||||
|
||||
expect(await service.getAllRacesPageData()).toBe(allRacesPageDataPresenter);
|
||||
expect(getAllRacesPageDataUseCase.execute).toHaveBeenCalledWith({});
|
||||
expect(allRacesPageDataPresenter.present).toHaveBeenCalledWith({ races: [], filters: { statuses: [], leagues: [] } });
|
||||
|
||||
expect(await service.getRaceResultsDetail('r1')).toBe(raceResultsDetailPresenter);
|
||||
expect(getRaceResultsDetailUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1' });
|
||||
expect(raceResultsDetailPresenter.present).toHaveBeenCalledWith({ race: null, results: [], penalties: [] });
|
||||
|
||||
expect(await service.getRaceWithSOF('r1')).toBe(raceWithSOFPresenter);
|
||||
expect(getRaceWithSOFUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1' });
|
||||
expect(raceWithSOFPresenter.present).toHaveBeenCalledWith({ race: null, strengthOfField: 0, participantCount: 0, registeredCount: 0, maxParticipants: 0 });
|
||||
|
||||
expect(await service.getRaceProtests('r1')).toBe(raceProtestsPresenter);
|
||||
expect(getRaceProtestsUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1' });
|
||||
expect(raceProtestsPresenter.present).toHaveBeenCalledWith({ protests: [], drivers: [] });
|
||||
|
||||
expect(await service.getRacePenalties('r1')).toBe(racePenaltiesPresenter);
|
||||
expect(getRacePenaltiesUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1' });
|
||||
expect(racePenaltiesPresenter.present).toHaveBeenCalledWith({ penalties: [], drivers: [] });
|
||||
|
||||
expect(await service.registerForRace({ raceId: 'r1', driverId: 'd1' } as any)).toBe(commandResultPresenter);
|
||||
expect(registerForRaceUseCase.execute).toHaveBeenCalled();
|
||||
expect(commandResultPresenter.present).toHaveBeenCalled();
|
||||
|
||||
expect(await service.withdrawFromRace({ raceId: 'r1', driverId: 'd1' } as any)).toBe(commandResultPresenter);
|
||||
expect(withdrawFromRaceUseCase.execute).toHaveBeenCalled();
|
||||
expect(commandResultPresenter.present).toHaveBeenCalled();
|
||||
|
||||
expect(await service.cancelRace({ raceId: 'r1' } as any, 'admin')).toBe(commandResultPresenter);
|
||||
expect(cancelRaceUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1', cancelledById: 'admin' });
|
||||
expect(commandResultPresenter.present).toHaveBeenCalled();
|
||||
|
||||
expect(await service.completeRace({ raceId: 'r1' } as any)).toBe(commandResultPresenter);
|
||||
expect(completeRaceUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1' });
|
||||
expect(commandResultPresenter.present).toHaveBeenCalled();
|
||||
|
||||
expect(await service.reopenRace({ raceId: 'r1' } as any, 'admin')).toBe(commandResultPresenter);
|
||||
expect(reopenRaceUseCase.execute).toHaveBeenCalledWith({ raceId: 'r1', reopenedById: 'admin' });
|
||||
expect(commandResultPresenter.present).toHaveBeenCalled();
|
||||
|
||||
expect(await service.fileProtest({} as any)).toBe(commandResultPresenter);
|
||||
expect(fileProtestUseCase.execute).toHaveBeenCalled();
|
||||
expect(commandResultPresenter.present).toHaveBeenCalled();
|
||||
|
||||
expect(await service.applyQuickPenalty({} as any)).toBe(commandResultPresenter);
|
||||
expect(quickPenaltyUseCase.execute).toHaveBeenCalled();
|
||||
expect(commandResultPresenter.present).toHaveBeenCalled();
|
||||
|
||||
expect(await service.applyPenalty({} as any)).toBe(commandResultPresenter);
|
||||
expect(applyPenaltyUseCase.execute).toHaveBeenCalled();
|
||||
expect(commandResultPresenter.present).toHaveBeenCalled();
|
||||
|
||||
expect(await service.requestProtestDefense({} as any)).toBe(commandResultPresenter);
|
||||
expect(requestProtestDefenseUseCase.execute).toHaveBeenCalled();
|
||||
expect(commandResultPresenter.present).toHaveBeenCalled();
|
||||
|
||||
expect(await service.reviewProtest({} as any)).toBe(commandResultPresenter);
|
||||
expect(reviewProtestUseCase.execute).toHaveBeenCalled();
|
||||
expect(commandResultPresenter.present).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Inject, Injectable, NotFoundException } from '@nestjs/common';
|
||||
|
||||
// DTOs
|
||||
import { GetRaceDetailParamsDTO } from './dtos/GetRaceDetailParamsDTO';
|
||||
@@ -116,55 +116,127 @@ export class RaceService {
|
||||
|
||||
async getAllRaces(): Promise<GetAllRacesPresenter> {
|
||||
this.logger.debug('[RaceService] Fetching all races.');
|
||||
await this.getAllRacesUseCase.execute({});
|
||||
const result = await this.getAllRacesUseCase.execute({});
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to get all races');
|
||||
}
|
||||
|
||||
const value = result.unwrap();
|
||||
this.getAllRacesPresenter.present(value);
|
||||
return this.getAllRacesPresenter;
|
||||
}
|
||||
|
||||
async getTotalRaces(): Promise<GetTotalRacesPresenter> {
|
||||
this.logger.debug('[RaceService] Fetching total races count.');
|
||||
await this.getTotalRacesUseCase.execute({});
|
||||
const result = await this.getTotalRacesUseCase.execute({});
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to get total races');
|
||||
}
|
||||
|
||||
const value = result.unwrap();
|
||||
this.getTotalRacesPresenter.present(value);
|
||||
return this.getTotalRacesPresenter;
|
||||
}
|
||||
|
||||
async importRaceResults(input: ImportRaceResultsDTO): Promise<ImportRaceResultsApiPresenter> {
|
||||
this.logger.debug('Importing race results:', input);
|
||||
await this.importRaceResultsApiUseCase.execute({ raceId: input.raceId, resultsFileContent: input.resultsFileContent });
|
||||
const result = await this.importRaceResultsApiUseCase.execute({ raceId: input.raceId, resultsFileContent: input.resultsFileContent });
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to import race results');
|
||||
}
|
||||
|
||||
const value = result.unwrap();
|
||||
this.importRaceResultsApiPresenter.present(value);
|
||||
return this.importRaceResultsApiPresenter;
|
||||
}
|
||||
|
||||
async getRaceDetail(params: GetRaceDetailParamsDTO): Promise<RaceDetailPresenter> {
|
||||
this.logger.debug('[RaceService] Fetching race detail:', params);
|
||||
await this.getRaceDetailUseCase.execute(params);
|
||||
const result = await this.getRaceDetailUseCase.execute(params);
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to get race detail');
|
||||
}
|
||||
|
||||
const value = result.unwrap();
|
||||
this.raceDetailPresenter.present(value);
|
||||
return this.raceDetailPresenter;
|
||||
}
|
||||
|
||||
async getRacesPageData(leagueId: string): Promise<RacesPageDataPresenter> {
|
||||
this.logger.debug('[RaceService] Fetching races page data.');
|
||||
await this.getRacesPageDataUseCase.execute({ leagueId });
|
||||
const result = await this.getRacesPageDataUseCase.execute({ leagueId });
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to get races page data');
|
||||
}
|
||||
|
||||
const value = result.unwrap();
|
||||
this.racesPageDataPresenter.present(value);
|
||||
return this.racesPageDataPresenter;
|
||||
}
|
||||
|
||||
async getAllRacesPageData(): Promise<AllRacesPageDataPresenter> {
|
||||
this.logger.debug('[RaceService] Fetching all races page data.');
|
||||
await this.getAllRacesPageDataUseCase.execute({});
|
||||
const result = await this.getAllRacesPageDataUseCase.execute({});
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to get all races page data');
|
||||
}
|
||||
|
||||
const value = result.unwrap();
|
||||
this.allRacesPageDataPresenter.present(value);
|
||||
return this.allRacesPageDataPresenter;
|
||||
}
|
||||
|
||||
async getRaceResultsDetail(raceId: string): Promise<RaceResultsDetailPresenter> {
|
||||
this.logger.debug('[RaceService] Fetching race results detail:', { raceId });
|
||||
await this.getRaceResultsDetailUseCase.execute({ raceId });
|
||||
const result = await this.getRaceResultsDetailUseCase.execute({ raceId });
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to get race results detail');
|
||||
}
|
||||
|
||||
const value = result.unwrap();
|
||||
this.raceResultsDetailPresenter.present(value);
|
||||
return this.raceResultsDetailPresenter;
|
||||
}
|
||||
|
||||
async getRaceWithSOF(raceId: string): Promise<RaceWithSOFPresenter> {
|
||||
this.logger.debug('[RaceService] Fetching race with SOF:', { raceId });
|
||||
await this.getRaceWithSOFUseCase.execute({ raceId });
|
||||
const result = await this.getRaceWithSOFUseCase.execute({ raceId });
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to get race with SOF');
|
||||
}
|
||||
|
||||
const value = result.unwrap();
|
||||
this.raceWithSOFPresenter.present(value);
|
||||
return this.raceWithSOFPresenter;
|
||||
}
|
||||
|
||||
async getRaceProtests(raceId: string): Promise<RaceProtestsPresenter> {
|
||||
this.logger.debug('[RaceService] Fetching race protests:', { raceId });
|
||||
await this.getRaceProtestsUseCase.execute({ raceId });
|
||||
const result = await this.getRaceProtestsUseCase.execute({ raceId });
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to get race protests');
|
||||
}
|
||||
|
||||
const value = result.unwrap();
|
||||
this.raceProtestsPresenter.present(value);
|
||||
return this.raceProtestsPresenter;
|
||||
}
|
||||
|
||||
@@ -186,67 +258,145 @@ export class RaceService {
|
||||
|
||||
async getRacePenalties(raceId: string): Promise<RacePenaltiesPresenter> {
|
||||
this.logger.debug('[RaceService] Fetching race penalties:', { raceId });
|
||||
await this.getRacePenaltiesUseCase.execute({ raceId });
|
||||
const result = await this.getRacePenaltiesUseCase.execute({ raceId });
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to get race penalties');
|
||||
}
|
||||
|
||||
const value = result.unwrap();
|
||||
this.racePenaltiesPresenter.present(value);
|
||||
return this.racePenaltiesPresenter;
|
||||
}
|
||||
|
||||
async registerForRace(params: RegisterForRaceParamsDTO): Promise<CommandResultPresenter> {
|
||||
this.logger.debug('[RaceService] Registering for race:', params);
|
||||
await this.registerForRaceUseCase.execute(params);
|
||||
const result = await this.registerForRaceUseCase.execute(params);
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to register for race');
|
||||
}
|
||||
|
||||
this.commandResultPresenter.present();
|
||||
return this.commandResultPresenter;
|
||||
}
|
||||
|
||||
async withdrawFromRace(params: WithdrawFromRaceParamsDTO): Promise<CommandResultPresenter> {
|
||||
this.logger.debug('[RaceService] Withdrawing from race:', params);
|
||||
await this.withdrawFromRaceUseCase.execute(params);
|
||||
const result = await this.withdrawFromRaceUseCase.execute(params);
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to withdraw from race');
|
||||
}
|
||||
|
||||
this.commandResultPresenter.present();
|
||||
return this.commandResultPresenter;
|
||||
}
|
||||
|
||||
async cancelRace(params: RaceActionParamsDTO, cancelledById: string): Promise<CommandResultPresenter> {
|
||||
this.logger.debug('[RaceService] Cancelling race:', params);
|
||||
await this.cancelRaceUseCase.execute({ raceId: params.raceId, cancelledById });
|
||||
const result = await this.cancelRaceUseCase.execute({ raceId: params.raceId, cancelledById });
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to cancel race');
|
||||
}
|
||||
|
||||
this.commandResultPresenter.present();
|
||||
return this.commandResultPresenter;
|
||||
}
|
||||
|
||||
async completeRace(params: RaceActionParamsDTO): Promise<CommandResultPresenter> {
|
||||
this.logger.debug('[RaceService] Completing race:', params);
|
||||
await this.completeRaceUseCase.execute({ raceId: params.raceId });
|
||||
const result = await this.completeRaceUseCase.execute({ raceId: params.raceId });
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to complete race');
|
||||
}
|
||||
|
||||
this.commandResultPresenter.present();
|
||||
return this.commandResultPresenter;
|
||||
}
|
||||
|
||||
async reopenRace(params: RaceActionParamsDTO, reopenedById: string): Promise<CommandResultPresenter> {
|
||||
this.logger.debug('[RaceService] Re-opening race:', params);
|
||||
await this.reopenRaceUseCase.execute({ raceId: params.raceId, reopenedById });
|
||||
const result = await this.reopenRaceUseCase.execute({ raceId: params.raceId, reopenedById });
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to reopen race');
|
||||
}
|
||||
|
||||
this.commandResultPresenter.present();
|
||||
return this.commandResultPresenter;
|
||||
}
|
||||
|
||||
async fileProtest(command: FileProtestCommandDTO): Promise<CommandResultPresenter> {
|
||||
this.logger.debug('[RaceService] Filing protest:', command);
|
||||
await this.fileProtestUseCase.execute(command);
|
||||
const result = await this.fileProtestUseCase.execute(command);
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to file protest');
|
||||
}
|
||||
|
||||
this.commandResultPresenter.present();
|
||||
return this.commandResultPresenter;
|
||||
}
|
||||
|
||||
async applyQuickPenalty(command: QuickPenaltyCommandDTO): Promise<CommandResultPresenter> {
|
||||
this.logger.debug('[RaceService] Applying quick penalty:', command);
|
||||
await this.quickPenaltyUseCase.execute(command);
|
||||
const result = await this.quickPenaltyUseCase.execute(command);
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to apply quick penalty');
|
||||
}
|
||||
|
||||
this.commandResultPresenter.present();
|
||||
return this.commandResultPresenter;
|
||||
}
|
||||
|
||||
async applyPenalty(command: ApplyPenaltyCommandDTO): Promise<CommandResultPresenter> {
|
||||
this.logger.debug('[RaceService] Applying penalty:', command);
|
||||
await this.applyPenaltyUseCase.execute(command);
|
||||
const result = await this.applyPenaltyUseCase.execute(command);
|
||||
|
||||
if (result.isErr()) {
|
||||
// ApplyPenaltyUseCase errors don't have details, just code
|
||||
throw new NotFoundException('Failed to apply penalty');
|
||||
}
|
||||
|
||||
this.commandResultPresenter.present();
|
||||
return this.commandResultPresenter;
|
||||
}
|
||||
|
||||
async requestProtestDefense(command: RequestProtestDefenseCommandDTO): Promise<CommandResultPresenter> {
|
||||
this.logger.debug('[RaceService] Requesting protest defense:', command);
|
||||
await this.requestProtestDefenseUseCase.execute(command);
|
||||
const result = await this.requestProtestDefenseUseCase.execute(command);
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to request protest defense');
|
||||
}
|
||||
|
||||
this.commandResultPresenter.present();
|
||||
return this.commandResultPresenter;
|
||||
}
|
||||
|
||||
async reviewProtest(command: ReviewProtestCommandDTO): Promise<CommandResultPresenter> {
|
||||
this.logger.debug('[RaceService] Reviewing protest:', command);
|
||||
await this.reviewProtestUseCase.execute(command);
|
||||
const result = await this.reviewProtestUseCase.execute(command);
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new NotFoundException(error.details?.message ?? 'Failed to review protest');
|
||||
}
|
||||
|
||||
this.commandResultPresenter.present();
|
||||
return this.commandResultPresenter;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,8 @@
|
||||
import type { Result } from '@core/shared/application/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type {
|
||||
GetAllRacesPageDataResult,
|
||||
GetAllRacesPageDataErrorCode,
|
||||
} from '@core/racing/application/use-cases/GetAllRacesPageDataUseCase';
|
||||
import type { GetAllRacesPageDataResult } from '@core/racing/application/use-cases/GetAllRacesPageDataUseCase';
|
||||
import type { AllRacesPageDTO } from '../dtos/AllRacesPageDTO';
|
||||
|
||||
export type AllRacesPageDataResponseModel = AllRacesPageDTO;
|
||||
|
||||
export type GetAllRacesPageDataApplicationError = ApplicationErrorCode<
|
||||
GetAllRacesPageDataErrorCode,
|
||||
{ message: string }
|
||||
>;
|
||||
|
||||
export class AllRacesPageDataPresenter {
|
||||
private model: AllRacesPageDataResponseModel | null = null;
|
||||
|
||||
@@ -20,19 +10,10 @@ export class AllRacesPageDataPresenter {
|
||||
this.model = null;
|
||||
}
|
||||
|
||||
present(
|
||||
result: Result<GetAllRacesPageDataResult, GetAllRacesPageDataApplicationError>,
|
||||
): void {
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new Error(error.details?.message ?? 'Failed to get all races page data');
|
||||
}
|
||||
|
||||
const output = result.unwrap();
|
||||
|
||||
present(result: GetAllRacesPageDataResult): void {
|
||||
this.model = {
|
||||
races: output.races,
|
||||
filters: output.filters,
|
||||
races: result.races,
|
||||
filters: result.filters,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -51,4 +32,4 @@ export class AllRacesPageDataPresenter {
|
||||
get viewModel(): AllRacesPageDataResponseModel {
|
||||
return this.responseModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,9 @@
|
||||
import type { Result } from '@core/shared/application/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
|
||||
export interface CommandResultDTO {
|
||||
success: boolean;
|
||||
errorCode?: string;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export type CommandApplicationError = ApplicationErrorCode<
|
||||
string,
|
||||
{ message: string }
|
||||
>;
|
||||
|
||||
export class CommandResultPresenter {
|
||||
private model: CommandResultDTO | null = null;
|
||||
|
||||
@@ -19,17 +11,9 @@ export class CommandResultPresenter {
|
||||
this.model = null;
|
||||
}
|
||||
|
||||
present(result: Result<unknown, CommandApplicationError>): void {
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
this.model = {
|
||||
success: false,
|
||||
errorCode: error.code,
|
||||
message: error.details?.message,
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
present(): void {
|
||||
// For command use cases, if we get here, it was successful
|
||||
// The service handles errors by throwing exceptions
|
||||
this.model = { success: true };
|
||||
}
|
||||
|
||||
@@ -63,4 +47,4 @@ export class CommandResultPresenter {
|
||||
get viewModel(): CommandResultDTO {
|
||||
return this.responseModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
import type { GetAllRacesResult } from '@core/racing/application/use-cases/GetAllRacesUseCase';
|
||||
import type { AllRacesPageDTO } from '../dtos/AllRacesPageDTO';
|
||||
|
||||
export type GetAllRacesResponseModel = AllRacesPageDTO;
|
||||
|
||||
export class GetAllRacesPresenter implements UseCaseOutputPort<GetAllRacesResult> {
|
||||
export class GetAllRacesPresenter {
|
||||
private model: GetAllRacesResponseModel | null = null;
|
||||
|
||||
present(result: GetAllRacesResult): void {
|
||||
|
||||
@@ -1,18 +1,8 @@
|
||||
import type { Result } from '@core/shared/application/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type {
|
||||
GetTotalRacesResult,
|
||||
GetTotalRacesErrorCode,
|
||||
} from '@core/racing/application/use-cases/GetTotalRacesUseCase';
|
||||
import type { GetTotalRacesResult } from '@core/racing/application/use-cases/GetTotalRacesUseCase';
|
||||
import type { RaceStatsDTO } from '../dtos/RaceStatsDTO';
|
||||
|
||||
export type GetTotalRacesResponseModel = RaceStatsDTO;
|
||||
|
||||
export type GetTotalRacesApplicationError = ApplicationErrorCode<
|
||||
GetTotalRacesErrorCode,
|
||||
{ message: string }
|
||||
>;
|
||||
|
||||
export class GetTotalRacesPresenter {
|
||||
private model: GetTotalRacesResponseModel | null = null;
|
||||
|
||||
@@ -20,16 +10,9 @@ export class GetTotalRacesPresenter {
|
||||
this.model = null;
|
||||
}
|
||||
|
||||
present(result: Result<GetTotalRacesResult, GetTotalRacesApplicationError>): void {
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new Error(error.details?.message ?? 'Failed to get total races');
|
||||
}
|
||||
|
||||
const output = result.unwrap();
|
||||
|
||||
present(result: GetTotalRacesResult): void {
|
||||
this.model = {
|
||||
totalRaces: output.totalRaces,
|
||||
totalRaces: result.totalRaces,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,8 @@
|
||||
import type { Result } from '@core/shared/application/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type {
|
||||
ImportRaceResultsApiResult,
|
||||
ImportRaceResultsApiErrorCode,
|
||||
} from '@core/racing/application/use-cases/ImportRaceResultsApiUseCase';
|
||||
import type { ImportRaceResultsApiResult } from '@core/racing/application/use-cases/ImportRaceResultsApiUseCase';
|
||||
import { ImportRaceResultsSummaryDTO } from '../dtos/ImportRaceResultsSummaryDTO';
|
||||
|
||||
export type ImportRaceResultsApiResponseModel = ImportRaceResultsSummaryDTO;
|
||||
|
||||
export type ImportRaceResultsApiApplicationError = ApplicationErrorCode<
|
||||
ImportRaceResultsApiErrorCode,
|
||||
{ message: string }
|
||||
>;
|
||||
|
||||
export class ImportRaceResultsApiPresenter {
|
||||
private model: ImportRaceResultsApiResponseModel | null = null;
|
||||
|
||||
@@ -20,22 +10,13 @@ export class ImportRaceResultsApiPresenter {
|
||||
this.model = null;
|
||||
}
|
||||
|
||||
present(
|
||||
result: Result<ImportRaceResultsApiResult, ImportRaceResultsApiApplicationError>,
|
||||
): void {
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new Error(error.details?.message ?? 'Failed to import race results');
|
||||
}
|
||||
|
||||
const output = result.unwrap();
|
||||
|
||||
present(result: ImportRaceResultsApiResult): void {
|
||||
this.model = {
|
||||
success: output.success,
|
||||
raceId: output.raceId,
|
||||
driversProcessed: output.driversProcessed,
|
||||
resultsRecorded: output.resultsRecorded,
|
||||
errors: output.errors,
|
||||
success: result.success,
|
||||
raceId: result.raceId,
|
||||
driversProcessed: result.driversProcessed,
|
||||
resultsRecorded: result.resultsRecorded,
|
||||
errors: result.errors,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
import type { GetRaceDetailResult } from '@core/racing/application/use-cases/GetRaceDetailUseCase';
|
||||
import type { DriverRatingProvider } from '@core/racing/application/ports/DriverRatingProvider';
|
||||
import type { IImageServicePort } from '@core/racing/application/ports/IImageServicePort';
|
||||
@@ -12,7 +11,7 @@ import type { RaceDetailUserResultDTO } from '../dtos/RaceDetailUserResultDTO';
|
||||
|
||||
export type GetRaceDetailResponseModel = RaceDetailDTO;
|
||||
|
||||
export class RaceDetailPresenter implements UseCaseOutputPort<GetRaceDetailResult> {
|
||||
export class RaceDetailPresenter {
|
||||
private result: GetRaceDetailResult | null = null;
|
||||
|
||||
constructor(
|
||||
@@ -118,4 +117,4 @@ export class RaceDetailPresenter implements UseCaseOutputPort<GetRaceDetailResul
|
||||
const positionBonus = Math.max(0, (20 - position) * 2);
|
||||
return baseChange + positionBonus;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,9 @@
|
||||
import type { Result } from '@core/shared/application/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type {
|
||||
GetRacePenaltiesResult,
|
||||
GetRacePenaltiesErrorCode,
|
||||
} from '@core/racing/application/use-cases/GetRacePenaltiesUseCase';
|
||||
import type { GetRacePenaltiesResult } from '@core/racing/application/use-cases/GetRacePenaltiesUseCase';
|
||||
import type { RacePenaltiesDTO } from '../dtos/RacePenaltiesDTO';
|
||||
import type { RacePenaltyDTO } from '../dtos/RacePenaltyDTO';
|
||||
|
||||
export type GetRacePenaltiesResponseModel = RacePenaltiesDTO;
|
||||
|
||||
export type GetRacePenaltiesApplicationError = ApplicationErrorCode<
|
||||
GetRacePenaltiesErrorCode,
|
||||
{ message: string }
|
||||
>;
|
||||
|
||||
export class RacePenaltiesPresenter {
|
||||
private model: GetRacePenaltiesResponseModel | null = null;
|
||||
|
||||
@@ -21,15 +11,8 @@ export class RacePenaltiesPresenter {
|
||||
this.model = null;
|
||||
}
|
||||
|
||||
present(result: Result<GetRacePenaltiesResult, GetRacePenaltiesApplicationError>): void {
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new Error(error.details?.message ?? 'Failed to get race penalties');
|
||||
}
|
||||
|
||||
const output = result.unwrap();
|
||||
|
||||
const penalties: RacePenaltyDTO[] = output.penalties.map(penalty => ({
|
||||
present(result: GetRacePenaltiesResult): void {
|
||||
const penalties: RacePenaltyDTO[] = result.penalties.map(penalty => ({
|
||||
id: penalty.id,
|
||||
driverId: penalty.driverId,
|
||||
type: penalty.type,
|
||||
@@ -41,7 +24,7 @@ export class RacePenaltiesPresenter {
|
||||
} as RacePenaltyDTO));
|
||||
|
||||
const driverMap: Record<string, string> = {};
|
||||
output.drivers.forEach(driver => {
|
||||
result.drivers.forEach(driver => {
|
||||
driverMap[driver.id] = driver.name.toString();
|
||||
});
|
||||
|
||||
@@ -66,4 +49,4 @@ export class RacePenaltiesPresenter {
|
||||
get viewModel(): GetRacePenaltiesResponseModel {
|
||||
return this.responseModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,9 @@
|
||||
import type { Result } from '@core/shared/application/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type {
|
||||
GetRaceProtestsResult,
|
||||
GetRaceProtestsErrorCode,
|
||||
} from '@core/racing/application/use-cases/GetRaceProtestsUseCase';
|
||||
import type { GetRaceProtestsResult } from '@core/racing/application/use-cases/GetRaceProtestsUseCase';
|
||||
import type { RaceProtestsDTO } from '../dtos/RaceProtestsDTO';
|
||||
import type { RaceProtestDTO } from '../dtos/RaceProtestDTO';
|
||||
|
||||
export type GetRaceProtestsResponseModel = RaceProtestsDTO;
|
||||
|
||||
export type GetRaceProtestsApplicationError = ApplicationErrorCode<
|
||||
GetRaceProtestsErrorCode,
|
||||
{ message: string }
|
||||
>;
|
||||
|
||||
export class RaceProtestsPresenter {
|
||||
private model: GetRaceProtestsResponseModel | null = null;
|
||||
|
||||
@@ -21,15 +11,8 @@ export class RaceProtestsPresenter {
|
||||
this.model = null;
|
||||
}
|
||||
|
||||
present(result: Result<GetRaceProtestsResult, GetRaceProtestsApplicationError>): void {
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new Error(error.details?.message ?? 'Failed to get race protests');
|
||||
}
|
||||
|
||||
const output = result.unwrap();
|
||||
|
||||
const protests: RaceProtestDTO[] = output.protests.map(protest => ({
|
||||
present(result: GetRaceProtestsResult): void {
|
||||
const protests: RaceProtestDTO[] = result.protests.map(protest => ({
|
||||
id: protest.id,
|
||||
protestingDriverId: protest.protestingDriverId,
|
||||
accusedDriverId: protest.accusedDriverId,
|
||||
@@ -42,7 +25,7 @@ export class RaceProtestsPresenter {
|
||||
} as RaceProtestDTO));
|
||||
|
||||
const driverMap: Record<string, string> = {};
|
||||
output.drivers.forEach(driver => {
|
||||
result.drivers.forEach(driver => {
|
||||
driverMap[driver.id] = driver.name.toString();
|
||||
});
|
||||
|
||||
@@ -67,4 +50,4 @@ export class RaceProtestsPresenter {
|
||||
get viewModel(): GetRaceProtestsResponseModel {
|
||||
return this.responseModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,8 @@
|
||||
import type { Result } from '@core/shared/application/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type {
|
||||
GetRaceWithSOFResult,
|
||||
GetRaceWithSOFErrorCode,
|
||||
} from '@core/racing/application/use-cases/GetRaceWithSOFUseCase';
|
||||
import type { GetRaceWithSOFResult } from '@core/racing/application/use-cases/GetRaceWithSOFUseCase';
|
||||
import type { RaceWithSOFDTO } from '../dtos/RaceWithSOFDTO';
|
||||
|
||||
export type GetRaceWithSOFResponseModel = RaceWithSOFDTO;
|
||||
|
||||
export type GetRaceWithSOFApplicationError = ApplicationErrorCode<
|
||||
GetRaceWithSOFErrorCode,
|
||||
{ message: string }
|
||||
>;
|
||||
|
||||
export class RaceWithSOFPresenter {
|
||||
private model: GetRaceWithSOFResponseModel | null = null;
|
||||
|
||||
@@ -20,27 +10,11 @@ export class RaceWithSOFPresenter {
|
||||
this.model = null;
|
||||
}
|
||||
|
||||
present(result: Result<GetRaceWithSOFResult, GetRaceWithSOFApplicationError>): void {
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
if (error.code === 'RACE_NOT_FOUND') {
|
||||
this.model = {
|
||||
id: '',
|
||||
track: '',
|
||||
strengthOfField: null,
|
||||
} as RaceWithSOFDTO;
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error(error.details?.message ?? 'Failed to get race with SOF');
|
||||
}
|
||||
|
||||
const output = result.unwrap();
|
||||
|
||||
present(result: GetRaceWithSOFResult): void {
|
||||
this.model = {
|
||||
id: output.race.id,
|
||||
track: output.race.track,
|
||||
strengthOfField: output.strengthOfField,
|
||||
id: result.race.id,
|
||||
track: result.race.track,
|
||||
strengthOfField: result.strengthOfField,
|
||||
} as RaceWithSOFDTO;
|
||||
}
|
||||
|
||||
@@ -59,4 +33,4 @@ export class RaceWithSOFPresenter {
|
||||
get viewModel(): GetRaceWithSOFResponseModel {
|
||||
return this.responseModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,9 @@
|
||||
import type { Result } from '@core/shared/application/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type {
|
||||
GetRacesPageDataResult,
|
||||
GetRacesPageDataErrorCode,
|
||||
} from '@core/racing/application/use-cases/GetRacesPageDataUseCase';
|
||||
import type { GetRacesPageDataResult } from '@core/racing/application/use-cases/GetRacesPageDataUseCase';
|
||||
import type { RacesPageDataDTO } from '../dtos/RacesPageDataDTO';
|
||||
import type { RacesPageDataRaceDTO } from '../dtos/RacesPageDataRaceDTO';
|
||||
|
||||
export type GetRacesPageDataResponseModel = RacesPageDataDTO;
|
||||
|
||||
export type GetRacesPageDataApplicationError = ApplicationErrorCode<
|
||||
GetRacesPageDataErrorCode,
|
||||
{ message: string }
|
||||
>;
|
||||
|
||||
export class RacesPageDataPresenter {
|
||||
private model: GetRacesPageDataResponseModel | null = null;
|
||||
|
||||
@@ -21,17 +11,8 @@ export class RacesPageDataPresenter {
|
||||
this.model = null;
|
||||
}
|
||||
|
||||
present(
|
||||
result: Result<GetRacesPageDataResult, GetRacesPageDataApplicationError>,
|
||||
): void {
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new Error(error.details?.message ?? 'Failed to get races page data');
|
||||
}
|
||||
|
||||
const output = result.unwrap();
|
||||
|
||||
const races: RacesPageDataRaceDTO[] = output.races.map(({ race, leagueName }) => ({
|
||||
present(result: GetRacesPageDataResult): void {
|
||||
const races: RacesPageDataRaceDTO[] = result.races.map(({ race, leagueName }) => ({
|
||||
id: race.id,
|
||||
track: race.track,
|
||||
car: race.car,
|
||||
@@ -63,4 +44,4 @@ export class RacesPageDataPresenter {
|
||||
get viewModel(): GetRacesPageDataResponseModel {
|
||||
return this.responseModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user