refactor dtos to ports

This commit is contained in:
2025-12-19 13:07:38 +01:00
parent 08ec2af5bf
commit 2ab86ec9bd
42 changed files with 83 additions and 81 deletions

View File

@@ -1,4 +0,0 @@
export interface ApproveLeagueJoinRequestUseCaseParams {
leagueId: string;
requestId: string;
}

View File

@@ -1,4 +0,0 @@
export interface ApproveTeamJoinRequestCommandDTO {
teamId: string;
requestId: string;
}

View File

@@ -1,3 +0,0 @@
export interface CancelRaceCommandDTO {
raceId: string;
}

View File

@@ -1,3 +0,0 @@
export interface CompleteRaceCommandDTO {
raceId: string;
}

View File

@@ -1,3 +0,0 @@
export interface DashboardOverviewParams {
driverId: string;
}

View File

@@ -1,3 +0,0 @@
export interface GetDriverTeamQueryParamsDTO {
driverId: string;
}

View File

@@ -1,3 +0,0 @@
export interface GetLeagueJoinRequestsUseCaseParams {
leagueId: string;
}

View File

@@ -1,4 +0,0 @@
export interface GetTeamDetailsQueryParamsDTO {
teamId: string;
driverId: string;
}

View File

@@ -1,3 +0,0 @@
export interface GetTeamJoinRequestsQueryParamsDTO {
teamId: string;
}

View File

@@ -1,3 +0,0 @@
export interface GetTeamMembersQueryParamsDTO {
teamId: string;
}

View File

@@ -1,8 +1,10 @@
import type { LeagueVisibilityType } from '../../domain/value-objects/LeagueVisibility';
import type { StewardingDecisionMode } from '../../domain/entities/League'; import type { StewardingDecisionMode } from '../../domain/entities/League';
import type { LeagueVisibilityType } from '../../domain/value-objects/LeagueVisibility';
export type LeagueStructureMode = 'solo' | 'fixedTeams'; export type LeagueStructureMode = 'solo' | 'fixedTeams';
// TODO this is way too much for a DTO. it must be pure InputPort or OutputPort
/** /**
* League visibility determines public visibility and ranking status. * League visibility determines public visibility and ranking status.
* - 'ranked': Public, competitive, affects driver ratings. Requires min 10 drivers. * - 'ranked': Public, competitive, affects driver ratings. Requires min 10 drivers.

View File

@@ -1,3 +0,0 @@
export interface RejectTeamJoinRequestCommandDTO {
requestId: string;
}

View File

@@ -1,4 +0,0 @@
export interface WithdrawFromRaceCommandDTO {
raceId: string;
driverId: string;
}

View File

@@ -1,4 +1,4 @@
export interface AcceptSponsorshipRequestDTO { export interface AcceptSponsorshipInputPort {
requestId: string; requestId: string;
respondedBy: string; // driverId of the person accepting respondedBy: string; // driverId of the person accepting
} }

View File

@@ -0,0 +1,4 @@
export interface ApproveLeagueJoinRequestInputPort {
leagueId: string;
requestId: string;
}

View File

@@ -0,0 +1,4 @@
export interface ApproveTeamJoinRequestInputPort {
teamId: string;
requestId: string;
}

View File

@@ -0,0 +1,3 @@
export interface CancelRaceInputPort {
raceId: string;
}

View File

@@ -4,6 +4,6 @@
* Scheduled job that checks for race events with expired stewarding windows * Scheduled job that checks for race events with expired stewarding windows
* and closes them, triggering final results notifications. * and closes them, triggering final results notifications.
*/ */
export interface CloseRaceEventStewardingCommand { export interface CloseRaceEventStewardingInputPort {
// No parameters needed - finds all expired events automatically // No parameters needed - finds all expired events automatically
} }

View File

@@ -1,4 +1,4 @@
export interface CompleteDriverOnboardingCommand { export interface CompleteDriverOnboardingInputPort {
userId: string; userId: string;
firstName: string; firstName: string;
lastName: string; lastName: string;

View File

@@ -0,0 +1,3 @@
export interface CompleteRaceInputPort {
raceId: string;
}

View File

@@ -1,6 +1,6 @@
import type { LeagueVisibilityInput } from './LeagueVisibilityInput'; import type { LeagueVisibilityInput } from '../../dtos/LeagueVisibilityInput';
export interface CreateLeagueWithSeasonAndScoringCommand { export interface CreateLeagueWithSeasonAndScoringInputPort {
name: string; name: string;
description?: string; description?: string;
/** /**

View File

@@ -1,4 +1,4 @@
export interface CreateSponsorCommand { export interface CreateSponsorInputPort {
name: string; name: string;
contactEmail: string; contactEmail: string;
websiteUrl?: string; websiteUrl?: string;

View File

@@ -1,4 +1,4 @@
export interface CreateTeamCommandDTO { export interface CreateTeamInputPort {
name: string; name: string;
tag: string; tag: string;
description: string; description: string;

View File

@@ -0,0 +1,3 @@
export interface DashboardOverviewInputPort {
driverId: string;
}

View File

@@ -0,0 +1,3 @@
export interface DriverTeamInputPort {
driverId: string;
}

View File

@@ -1,6 +1,6 @@
import type { ProtestIncident } from '../../domain/entities/Protest'; import { ProtestIncident } from "@/racing/domain/entities/ProtestIncident";
export interface FileProtestCommand { export interface FileProtestInputPort {
raceId: string; raceId: string;
protestingDriverId: string; protestingDriverId: string;
accusedDriverId: string; accusedDriverId: string;

View File

@@ -1,4 +1,4 @@
export interface JoinLeagueCommandDTO { export interface JoinLeagueInputPort {
leagueId: string; leagueId: string;
driverId: string; driverId: string;
} }

View File

@@ -1,4 +1,4 @@
export interface JoinTeamCommandDTO { export interface JoinTeamInputPort {
teamId: string; teamId: string;
driverId: string; driverId: string;
} }

View File

@@ -0,0 +1,3 @@
export interface LeagueJoinRequestsInputPort {
leagueId: string;
}

View File

@@ -1,4 +1,4 @@
export interface LeaveTeamCommandDTO { export interface LeaveTeamInputPort {
teamId: string; teamId: string;
driverId: string; driverId: string;
} }

View File

@@ -1,4 +1,4 @@
export interface RegisterForRaceCommandDTO { export interface RegisterForRaceInputPort {
raceId: string; raceId: string;
leagueId: string; leagueId: string;
driverId: string; driverId: string;

View File

@@ -0,0 +1,3 @@
export interface RejectTeamJoinRequestInputPort {
requestId: string;
}

View File

@@ -0,0 +1,4 @@
export interface TeamDetailsInputPort {
teamId: string;
driverId: string;
}

View File

@@ -0,0 +1,3 @@
export interface TeamJoinRequestsInputPort {
teamId: string;
}

View File

@@ -0,0 +1,3 @@
export interface TeamMembersInputPort {
teamId: string;
}

View File

@@ -1,6 +1,6 @@
import type { Team } from '../../domain/entities/Team'; import type { Team } from '../../../domain/entities/Team';
export interface UpdateTeamCommandDTO { export interface UpdateTeamInputPort {
teamId: string; teamId: string;
updates: Partial<Pick<Team, 'name' | 'tag' | 'description' | 'leagues'>>; updates: Partial<Pick<Team, 'name' | 'tag' | 'description' | 'leagues'>>;
updatedBy: string; updatedBy: string;

View File

@@ -0,0 +1,4 @@
export interface WithdrawFromRaceInputPort {
raceId: string;
driverId: string;
}

View File

@@ -1,20 +1,20 @@
import type { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository';
import type {
TeamMembership,
TeamJoinRequest,
} from '../../domain/types/TeamMembership';
import type { ApproveTeamJoinRequestCommandDTO } from '../dtos/ApproveTeamJoinRequestCommandDTO';
import type { AsyncUseCase } from '@core/shared/application'; import type { AsyncUseCase } from '@core/shared/application';
import { Result } from '@core/shared/application/Result'; import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository';
import type {
TeamJoinRequest,
TeamMembership,
} from '../../domain/types/TeamMembership';
import type { ApproveTeamJoinRequestInputPort } from '../ports/input/ApproveTeamJoinRequestInputPort';
export class ApproveTeamJoinRequestUseCase export class ApproveTeamJoinRequestUseCase
implements AsyncUseCase<ApproveTeamJoinRequestCommandDTO, void, string> { implements AsyncUseCase<ApproveTeamJoinRequestInputPort, void, string> {
constructor( constructor(
private readonly membershipRepository: ITeamMembershipRepository, private readonly membershipRepository: ITeamMembershipRepository,
) {} ) {}
async execute(command: ApproveTeamJoinRequestCommandDTO): Promise<Result<void, ApplicationErrorCode<string>>> { async execute(command: ApproveTeamJoinRequestInputPort): Promise<Result<void, ApplicationErrorCode<string>>> {
const { teamId, requestId } = command; const { teamId, requestId } = command;
const allRequests: TeamJoinRequest[] = await this.membershipRepository.getJoinRequests(teamId); const allRequests: TeamJoinRequest[] = await this.membershipRepository.getJoinRequests(teamId);

View File

@@ -1,27 +1,27 @@
import type { ITeamRepository } from '../../domain/repositories/ITeamRepository'; import type { AsyncUseCase, Logger } from '@core/shared/application';
import { Result as SharedResult } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository'; import type { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository';
import type { ITeamRepository } from '../../domain/repositories/ITeamRepository';
import type { import type {
TeamMembership, TeamMembership,
TeamMembershipStatus, TeamMembershipStatus,
TeamRole, TeamRole,
} from '../../domain/types/TeamMembership'; } from '../../domain/types/TeamMembership';
import type { JoinTeamCommandDTO } from '../dtos/JoinTeamCommandDTO'; import type { JoinTeamInputPort } from '../ports/input/JoinTeamInputPort';
import type { AsyncUseCase, Logger } from '@core/shared/application';
import { Result as SharedResult } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
type JoinTeamErrorCode = 'ALREADY_IN_TEAM' | 'ALREADY_MEMBER' | 'TEAM_NOT_FOUND' | 'REPOSITORY_ERROR'; type JoinTeamErrorCode = 'ALREADY_IN_TEAM' | 'ALREADY_MEMBER' | 'TEAM_NOT_FOUND' | 'REPOSITORY_ERROR';
type JoinTeamApplicationError = ApplicationErrorCode<JoinTeamErrorCode, { message: string }>; type JoinTeamApplicationError = ApplicationErrorCode<JoinTeamErrorCode, { message: string }>;
export class JoinTeamUseCase implements AsyncUseCase<JoinTeamCommandDTO, void, JoinTeamErrorCode> { export class JoinTeamUseCase implements AsyncUseCase<JoinTeamInputPort, void, JoinTeamErrorCode> {
constructor( constructor(
private readonly teamRepository: ITeamRepository, private readonly teamRepository: ITeamRepository,
private readonly membershipRepository: ITeamMembershipRepository, private readonly membershipRepository: ITeamMembershipRepository,
private readonly logger: Logger, private readonly logger: Logger,
) {} ) {}
async execute(command: JoinTeamCommandDTO): Promise<SharedResult<void, JoinTeamApplicationError>> { async execute(command: JoinTeamInputPort): Promise<SharedResult<void, JoinTeamApplicationError>> {
this.logger.debug('Attempting to join team', { command }); this.logger.debug('Attempting to join team', { command });
const { teamId, driverId } = command; const { teamId, driverId } = command;

View File

@@ -1,20 +1,20 @@
import type { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository';
import type { LeaveTeamCommandDTO } from '../dtos/LeaveTeamCommandDTO';
import type { AsyncUseCase, Logger } from '@core/shared/application'; import type { AsyncUseCase, Logger } from '@core/shared/application';
import { Result as SharedResult } from '@core/shared/application/Result'; import { Result as SharedResult } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository';
import type { LeaveTeamInputPort } from '../ports/input/LeaveTeamInputPort';
type LeaveTeamErrorCode = 'NOT_MEMBER' | 'OWNER_CANNOT_LEAVE' | 'REPOSITORY_ERROR'; type LeaveTeamErrorCode = 'NOT_MEMBER' | 'OWNER_CANNOT_LEAVE' | 'REPOSITORY_ERROR';
type LeaveTeamApplicationError = ApplicationErrorCode<LeaveTeamErrorCode, { message: string }>; type LeaveTeamApplicationError = ApplicationErrorCode<LeaveTeamErrorCode, { message: string }>;
export class LeaveTeamUseCase implements AsyncUseCase<LeaveTeamCommandDTO, void, LeaveTeamErrorCode> { export class LeaveTeamUseCase implements AsyncUseCase<LeaveTeamInputPort, void, LeaveTeamErrorCode> {
constructor( constructor(
private readonly membershipRepository: ITeamMembershipRepository, private readonly membershipRepository: ITeamMembershipRepository,
private readonly logger: Logger, private readonly logger: Logger,
) {} ) {}
async execute(command: LeaveTeamCommandDTO): Promise<SharedResult<void, LeaveTeamApplicationError>> { async execute(command: LeaveTeamInputPort): Promise<SharedResult<void, LeaveTeamApplicationError>> {
this.logger.debug('Attempting to leave team', { command }); this.logger.debug('Attempting to leave team', { command });
const { teamId, driverId } = command; const { teamId, driverId } = command;

View File

@@ -1,14 +1,14 @@
import type { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository';
import type { RejectTeamJoinRequestCommandDTO } from '../dtos/RejectTeamJoinRequestCommandDTO';
import { Result } from '@core/shared/application/Result'; import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository';
import type { RejectTeamJoinRequestInputPort } from '../ports/input/RejectTeamJoinRequestInputPort';
export class RejectTeamJoinRequestUseCase { export class RejectTeamJoinRequestUseCase {
constructor( constructor(
private readonly membershipRepository: ITeamMembershipRepository, private readonly membershipRepository: ITeamMembershipRepository,
) {} ) {}
async execute(command: RejectTeamJoinRequestCommandDTO): Promise<Result<void, ApplicationErrorCode<'NO_ERROR'>>> { async execute(command: RejectTeamJoinRequestInputPort): Promise<Result<void, ApplicationErrorCode<'NO_ERROR'>>> {
const { requestId } = command; const { requestId } = command;
await this.membershipRepository.removeJoinRequest(requestId); await this.membershipRepository.removeJoinRequest(requestId);
return Result.ok(undefined); return Result.ok(undefined);

View File

@@ -1,9 +1,9 @@
import { Result } from '@core/shared/application/Result'; import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { ITeamRepository } from '../../domain/repositories/ITeamRepository';
import type { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository'; import type { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository';
import type { ITeamRepository } from '../../domain/repositories/ITeamRepository';
import type { UpdateTeamCommandDTO } from '../dtos/UpdateTeamCommandDTO'; import type { UpdateTeamInputPort } from '../ports/input/UpdateTeamInputPort';
type UpdateTeamErrorCode = 'INSUFFICIENT_PERMISSIONS' | 'TEAM_NOT_FOUND'; type UpdateTeamErrorCode = 'INSUFFICIENT_PERMISSIONS' | 'TEAM_NOT_FOUND';
@@ -13,7 +13,7 @@ export class UpdateTeamUseCase {
private readonly membershipRepository: ITeamMembershipRepository, private readonly membershipRepository: ITeamMembershipRepository,
) {} ) {}
async execute(command: UpdateTeamCommandDTO): Promise<Result<void, ApplicationErrorCode<UpdateTeamErrorCode>>> { async execute(command: UpdateTeamInputPort): Promise<Result<void, ApplicationErrorCode<UpdateTeamErrorCode>>> {
const { teamId, updates, updatedBy } = command; const { teamId, updates, updatedBy } = command;
const updaterMembership = await this.membershipRepository.getMembership(teamId, updatedBy); const updaterMembership = await this.membershipRepository.getMembership(teamId, updatedBy);