presenter refactoring

This commit is contained in:
2025-12-20 17:06:11 +01:00
parent 92be9d2e1b
commit e9d6f90bb2
109 changed files with 4159 additions and 1283 deletions

View File

@@ -13,30 +13,37 @@ import { LeagueAdminDTO } from './dtos/LeagueAdminDTO';
import { LeagueAdminPermissionsDTO } from './dtos/LeagueAdminPermissionsDTO';
import { LeagueAdminProtestsDTO } from './dtos/LeagueAdminProtestsDTO';
import { LeagueMembershipsDTO } from './dtos/LeagueMembershipsDTO';
import { LeagueOwnerSummaryDTO } from './dtos/LeagueOwnerSummaryDTO';
import { LeagueScheduleDTO } from './dtos/LeagueScheduleDTO';
import { LeagueSeasonSummaryDTO } from './dtos/LeagueSeasonSummaryDTO';
import { LeagueConfigFormModelDTO } from './dtos/LeagueConfigFormModelDTO';
import { LeagueStatsDTO } from './dtos/LeagueStatsDTO';
import { LeagueStandingsDTO } from './dtos/LeagueStandingsDTO';
import { GetLeagueWalletOutputDTO } from './dtos/GetLeagueWalletOutputDTO';
import { WithdrawFromLeagueWalletInputDTO } from './dtos/WithdrawFromLeagueWalletInputDTO';
import { WithdrawFromLeagueWalletOutputDTO } from './dtos/WithdrawFromLeagueWalletOutputDTO';
import { GetSeasonSponsorshipsOutputDTO } from './dtos/GetSeasonSponsorshipsOutputDTO';
import { GetLeagueRacesOutputDTO } from './dtos/GetLeagueRacesOutputDTO';
import { RejectJoinRequestOutputDTO } from './dtos/RejectJoinRequestOutputDTO';
import { RemoveLeagueMemberOutputDTO } from './dtos/RemoveLeagueMemberOutputDTO';
import { TransferLeagueOwnershipOutputDTO } from './dtos/TransferLeagueOwnershipOutputDTO';
import { UpdateLeagueMemberRoleOutputDTO } from './dtos/UpdateLeagueMemberRoleOutputDTO';
import { LeagueJoinRequestWithDriverDTO } from './dtos/LeagueJoinRequestWithDriverDTO';
import { ApproveLeagueJoinRequestDTO } from './dtos/ApproveLeagueJoinRequestDTO';
// Core imports for view models
import type { LeagueScoringConfigViewModel } from './presenters/LeagueScoringConfigPresenter';
import type { LeagueScoringPresetsViewModel } from './presenters/LeagueScoringPresetsPresenter';
import type { AllLeaguesWithCapacityDTO as AllLeaguesWithCapacityViewModel } from '../dtos/AllLeaguesWithCapacityDTO';
import type { GetLeagueJoinRequestsViewModel } from '@core/racing/application/presenters/IGetLeagueJoinRequestsPresenter';
import type { AllLeaguesWithCapacityDTO as AllLeaguesWithCapacityViewModel } from './dtos/AllLeaguesWithCapacityDTO';
import { TotalLeaguesDTO } from './dtos/TotalLeaguesDTO';
import type { ApproveLeagueJoinRequestDTO } from './dtos/ApproveLeagueJoinRequestDTO';
import type { JoinLeagueOutputDTO } from './dtos/JoinLeagueOutputDTO';
import type { GetLeagueAdminPermissionsViewModel } from '@core/racing/application/presenters/IGetLeagueAdminPermissionsPresenter';
import type { CreateLeagueViewModel } from './dtos/CreateLeagueDTO';
// Core imports
import type { Logger } from '@core/shared/application/Logger';
// Use cases
import { GetLeagueStandingsUseCase } from '@core/league/application/use-cases/GetLeagueStandingsUseCase';
import { GetLeagueStandingsUseCase } from '@core/racing/application/use-cases/GetLeagueStandingsUseCase';
import { ApproveLeagueJoinRequestUseCase } from '@core/racing/application/use-cases/ApproveLeagueJoinRequestUseCase';
import { CreateLeagueWithSeasonAndScoringUseCase } from '@core/racing/application/use-cases/CreateLeagueWithSeasonAndScoringUseCase';
import { GetAllLeaguesWithCapacityUseCase } from '@core/racing/application/use-cases/GetAllLeaguesWithCapacityUseCase';
@@ -67,22 +74,26 @@ import { AllLeaguesWithCapacityPresenter } from './presenters/AllLeaguesWithCapa
import { TotalLeaguesPresenter } from './presenters/TotalLeaguesPresenter';
import { LeagueScoringConfigPresenter } from './presenters/LeagueScoringConfigPresenter';
import { LeagueScoringPresetsPresenter } from './presenters/LeagueScoringPresetsPresenter';
import { mapApproveLeagueJoinRequestPortToDTO } from './presenters/ApproveLeagueJoinRequestPresenter';
import { ApproveLeagueJoinRequestPresenter } from './presenters/ApproveLeagueJoinRequestPresenter';
import { GetLeagueAdminPermissionsPresenter } from './presenters/GetLeagueAdminPermissionsPresenter';
import { mapGetLeagueOwnerSummaryOutputPortToDTO } from './presenters/GetLeagueOwnerSummaryPresenter';
import { GetLeagueOwnerSummaryPresenter } from './presenters/GetLeagueOwnerSummaryPresenter';
import { LeagueJoinRequestsPresenter } from './presenters/LeagueJoinRequestsPresenter';
import { mapGetLeagueScheduleOutputPortToDTO, mapGetLeagueScheduleOutputPortToRaceDTOs } from './presenters/LeagueSchedulePresenter';
import { LeagueSchedulePresenter, LeagueRacesPresenter } from './presenters/LeagueSchedulePresenter';
import { LeagueStatsPresenter } from './presenters/LeagueStatsPresenter';
import { mapRejectLeagueJoinRequestOutputPortToDTO } from './presenters/RejectLeagueJoinRequestPresenter';
import { mapRemoveLeagueMemberOutputPortToDTO } from './presenters/RemoveLeagueMemberPresenter';
import { mapUpdateLeagueMemberRoleOutputPortToDTO } from './presenters/UpdateLeagueMemberRolePresenter';
import { RejectLeagueJoinRequestPresenter } from './presenters/RejectLeagueJoinRequestPresenter';
import { RemoveLeagueMemberPresenter } from './presenters/RemoveLeagueMemberPresenter';
import { UpdateLeagueMemberRolePresenter } from './presenters/UpdateLeagueMemberRolePresenter';
import { CreateLeaguePresenter } from './presenters/CreateLeaguePresenter';
import { mapJoinLeagueOutputPortToDTO } from './presenters/JoinLeaguePresenter';
import { mapTransferLeagueOwnershipOutputPortToDTO } from './presenters/TransferLeagueOwnershipPresenter';
import { mapGetLeagueProtestsOutputPortToDTO } from './presenters/GetLeagueProtestsPresenter';
import { mapGetLeagueSeasonsOutputPortToDTO } from './presenters/GetLeagueSeasonsPresenter';
import { JoinLeaguePresenter } from './presenters/JoinLeaguePresenter';
import { TransferLeagueOwnershipPresenter } from './presenters/TransferLeagueOwnershipPresenter';
import { GetLeagueProtestsPresenter } from './presenters/GetLeagueProtestsPresenter';
import { GetLeagueSeasonsPresenter } from './presenters/GetLeagueSeasonsPresenter';
import { LeagueConfigPresenter } from './presenters/LeagueConfigPresenter';
import { LeagueStandingsPresenter } from './presenters/LeagueStandingsPresenter';
import { GetLeagueMembershipsPresenter } from './presenters/GetLeagueMembershipsPresenter';
import { LeagueOwnerSummaryPresenter } from './presenters/LeagueOwnerSummaryPresenter';
import { LeagueAdminPresenter } from './presenters/LeagueAdminPresenter';
import { GetSeasonSponsorshipsPresenter } from './presenters/GetSeasonSponsorshipsPresenter';
// Tokens
import { LOGGER_TOKEN } from './LeagueProviders';
@@ -140,7 +151,7 @@ export class LeagueService {
return presenter.getViewModel()!;
}
async getLeagueJoinRequests(leagueId: string): Promise<GetLeagueJoinRequestsViewModel> {
async getLeagueJoinRequests(leagueId: string): Promise<LeagueJoinRequestWithDriverDTO[]> {
this.logger.debug(`[LeagueService] Fetching join requests for league: ${leagueId}.`);
const result = await this.getLeagueJoinRequestsUseCase.execute({ leagueId });
if (result.isErr()) {
@@ -148,7 +159,7 @@ export class LeagueService {
}
const presenter = new LeagueJoinRequestsPresenter();
presenter.present(result.unwrap());
return presenter.getViewModel();
return presenter.getViewModel()!.joinRequests;
}
async approveLeagueJoinRequest(input: ApproveJoinRequestInputDTO): Promise<ApproveLeagueJoinRequestDTO> {
@@ -157,19 +168,27 @@ export class LeagueService {
if (result.isErr()) {
throw new Error(result.unwrapErr().code);
}
return mapApproveLeagueJoinRequestPortToDTO(result.unwrap());
const presenter = new ApproveLeagueJoinRequestPresenter();
presenter.present(result.unwrap());
return presenter.getViewModel()!;
}
async rejectLeagueJoinRequest(input: RejectJoinRequestInputDTO): Promise<RejectJoinRequestOutputDTO> {
this.logger.debug('Rejecting join request:', input);
const result = await this.rejectLeagueJoinRequestUseCase.execute({ requestId: input.requestId });
if (result.isErr()) {
throw new Error(result.unwrapErr().code);
const error = result.unwrapErr();
return {
success: false,
error: error.code,
};
}
return mapRejectLeagueJoinRequestOutputPortToDTO(result.unwrap());
const presenter = new RejectLeagueJoinRequestPresenter();
presenter.present(result.unwrap());
return presenter.getViewModel()!;
}
async getLeagueAdminPermissions(query: GetLeagueAdminPermissionsInputDTO): Promise<GetLeagueAdminPermissionsViewModel> {
async getLeagueAdminPermissions(query: GetLeagueAdminPermissionsInputDTO): Promise<LeagueAdminPermissionsDTO> {
this.logger.debug('Getting league admin permissions', { query });
const result = await this.getLeagueAdminPermissionsUseCase.execute({ leagueId: query.leagueId, performerDriverId: query.performerDriverId });
// This use case never errors
@@ -182,27 +201,41 @@ export class LeagueService {
this.logger.debug('Removing league member', { leagueId: input.leagueId, targetDriverId: input.targetDriverId });
const result = await this.removeLeagueMemberUseCase.execute({ leagueId: input.leagueId, targetDriverId: input.targetDriverId });
if (result.isErr()) {
throw new Error(result.unwrapErr().code);
const error = result.unwrapErr();
return {
success: false,
error: error.code,
};
}
return mapRemoveLeagueMemberOutputPortToDTO(result.unwrap());
const presenter = new RemoveLeagueMemberPresenter();
presenter.present(result.unwrap());
return presenter.getViewModel()!;
}
async updateLeagueMemberRole(input: UpdateLeagueMemberRoleInputDTO): Promise<UpdateLeagueMemberRoleOutputDTO> {
this.logger.debug('Updating league member role', { leagueId: input.leagueId, targetDriverId: input.targetDriverId, newRole: input.newRole });
const result = await this.updateLeagueMemberRoleUseCase.execute({ leagueId: input.leagueId, targetDriverId: input.targetDriverId, newRole: input.newRole });
if (result.isErr()) {
throw new Error(result.unwrapErr().code);
const error = result.unwrapErr();
return {
success: false,
error: error.code,
};
}
return mapUpdateLeagueMemberRoleOutputPortToDTO(result.unwrap());
const presenter = new UpdateLeagueMemberRolePresenter();
presenter.present(result.unwrap());
return presenter.getViewModel()!;
}
async getLeagueOwnerSummary(query: GetLeagueOwnerSummaryQueryDTO): Promise<LeagueOwnerSummaryDTO | null> {
async getLeagueOwnerSummary(query: GetLeagueOwnerSummaryQueryDTO): Promise<LeagueOwnerSummaryDTO> {
this.logger.debug('Getting league owner summary:', query);
const result = await this.getLeagueOwnerSummaryUseCase.execute({ ownerId: query.ownerId });
if (result.isErr()) {
throw new Error(result.unwrapErr().code);
}
return mapGetLeagueOwnerSummaryOutputPortToDTO(result.unwrap());
const presenter = new GetLeagueOwnerSummaryPresenter();
presenter.present(result.unwrap());
return presenter.getViewModel()!;
}
async getLeagueFullConfig(query: GetLeagueAdminConfigQueryDTO): Promise<LeagueConfigFormModelDTO | null> {
@@ -229,7 +262,9 @@ export class LeagueService {
if (result.isErr()) {
throw new Error(result.unwrapErr().code);
}
return mapGetLeagueProtestsOutputPortToDTO(result.unwrap());
const presenter = new GetLeagueProtestsPresenter();
presenter.present(result.unwrap());
return presenter.getViewModel()!;
}
async getLeagueSeasons(query: GetLeagueSeasonsQueryDTO): Promise<LeagueSeasonSummaryDTO[]> {
@@ -238,7 +273,9 @@ export class LeagueService {
if (result.isErr()) {
throw new Error(result.unwrapErr().code);
}
return mapGetLeagueSeasonsOutputPortToDTO(result.unwrap());
const presenter = new GetLeagueSeasonsPresenter();
presenter.present(result.unwrap());
return presenter.getViewModel()!;
}
async getLeagueMemberships(leagueId: string): Promise<LeagueMembershipsDTO> {
@@ -249,7 +286,7 @@ export class LeagueService {
}
const presenter = new GetLeagueMembershipsPresenter();
presenter.present(result.unwrap());
return presenter.getViewModel().memberships as LeagueMembershipsDTO;
return presenter.getViewModel()!.memberships;
}
async getLeagueStandings(leagueId: string): Promise<LeagueStandingsDTO> {
@@ -260,7 +297,7 @@ export class LeagueService {
}
const presenter = new LeagueStandingsPresenter();
presenter.present(result.unwrap());
return presenter.getViewModel();
return presenter.getViewModel()!;
}
async getLeagueSchedule(leagueId: string): Promise<LeagueScheduleDTO> {
@@ -279,7 +316,9 @@ export class LeagueService {
? leagueConfigResult.unwrap().league.name.toString()
: undefined;
return mapGetLeagueScheduleOutputPortToDTO(scheduleResult.unwrap(), leagueName);
const presenter = new LeagueSchedulePresenter();
presenter.present(scheduleResult.unwrap(), leagueName);
return presenter.getViewModel()!;
}
async getLeagueStats(leagueId: string): Promise<LeagueStatsDTO> {
@@ -315,7 +354,9 @@ export class LeagueService {
throw new Error(ownerSummaryResult.unwrapErr().code);
}
const ownerSummary = mapGetLeagueOwnerSummaryOutputPortToDTO(ownerSummaryResult.unwrap());
const ownerSummaryPresenter = new GetLeagueOwnerSummaryPresenter();
ownerSummaryPresenter.present(ownerSummaryResult.unwrap());
const ownerSummary = ownerSummaryPresenter.getViewModel()!;
const configPresenter = new LeagueConfigPresenter();
configPresenter.present(fullConfig);
@@ -323,7 +364,7 @@ export class LeagueService {
const adminPresenter = new LeagueAdminPresenter();
adminPresenter.present({
joinRequests: joinRequests.joinRequests,
joinRequests: joinRequests,
ownerSummary,
config: configForm,
protests,
@@ -358,7 +399,7 @@ export class LeagueService {
}
const presenter = new CreateLeaguePresenter();
presenter.present(result.unwrap());
return presenter.getViewModel();
return presenter.getViewModel()!;
}
async getLeagueScoringConfig(leagueId: string): Promise<LeagueScoringConfigViewModel | null> {
@@ -371,7 +412,7 @@ export class LeagueService {
this.logger.error('Error getting league scoring config', new Error(result.unwrapErr().code));
return null;
}
await presenter.present(result.unwrap());
presenter.present(result.unwrap());
return presenter.getViewModel();
} catch (error) {
this.logger.error('Error getting league scoring config', error instanceof Error ? error : new Error(String(error)));
@@ -403,7 +444,9 @@ export class LeagueService {
error: error.code,
};
}
return mapJoinLeagueOutputPortToDTO(result.unwrap());
const presenter = new JoinLeaguePresenter();
presenter.present(result.unwrap());
return presenter.getViewModel()!;
}
async transferLeagueOwnership(leagueId: string, currentOwnerId: string, newOwnerId: string): Promise<TransferLeagueOwnershipOutputDTO> {
@@ -417,7 +460,9 @@ export class LeagueService {
error: error.code,
};
}
return mapTransferLeagueOwnershipOutputPortToDTO(result.unwrap());
const presenter = new TransferLeagueOwnershipPresenter();
presenter.present(result.unwrap());
return presenter.getViewModel()!;
}
async getSeasonSponsorships(seasonId: string): Promise<GetSeasonSponsorshipsOutputDTO> {
@@ -428,11 +473,9 @@ export class LeagueService {
throw new Error(result.unwrapErr().code);
}
const value = result.unwrap();
return {
sponsorships: value?.sponsorships ?? [],
};
const presenter = new GetSeasonSponsorshipsPresenter();
presenter.present(result.unwrap());
return presenter.getViewModel()!;
}
async getRaces(leagueId: string): Promise<GetLeagueRacesOutputDTO> {
@@ -443,10 +486,11 @@ export class LeagueService {
throw new Error(result.unwrapErr().code);
}
const races = mapGetLeagueScheduleOutputPortToRaceDTOs(result.unwrap());
const presenter = new LeagueRacesPresenter();
presenter.present(result.unwrap());
return {
races,
races: presenter.getViewModel()!,
};
}
@@ -454,7 +498,7 @@ export class LeagueService {
this.logger.debug('Getting league wallet', { leagueId });
const result = await this.getLeagueWalletUseCase.execute({ leagueId });
if (result.isErr()) {
throw new Error(result.unwrapErr().message);
throw new Error(result.unwrapErr().code);
}
return result.unwrap();
}
@@ -471,9 +515,9 @@ export class LeagueService {
if (result.isErr()) {
const error = result.unwrapErr();
if (error.code === 'WITHDRAWAL_NOT_ALLOWED') {
return { success: false, message: error.message };
return { success: false, message: error.code };
}
throw new Error(error.message);
throw new Error(error.code);
}
return result.unwrap();
}