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 { LeagueVisibilityType } from '../../domain/value-objects/LeagueVisibility';
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.
* - '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;
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
* and closes them, triggering final results notifications.
*/
export interface CloseRaceEventStewardingCommand {
export interface CloseRaceEventStewardingInputPort {
// No parameters needed - finds all expired events automatically
}

View File

@@ -1,4 +1,4 @@
export interface CompleteDriverOnboardingCommand {
export interface CompleteDriverOnboardingInputPort {
userId: string;
firstName: 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;
description?: string;
/**

View File

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

View File

@@ -1,4 +1,4 @@
export interface CreateTeamCommandDTO {
export interface CreateTeamInputPort {
name: string;
tag: 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;
protestingDriverId: string;
accusedDriverId: string;

View File

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

View File

@@ -1,4 +1,4 @@
export interface JoinTeamCommandDTO {
export interface JoinTeamInputPort {
teamId: 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;
driverId: string;
}

View File

@@ -1,4 +1,4 @@
export interface RegisterForRaceCommandDTO {
export interface RegisterForRaceInputPort {
raceId: string;
leagueId: 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;
updates: Partial<Pick<Team, 'name' | 'tag' | 'description' | 'leagues'>>;
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 { Result } from '@core/shared/application/Result';
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
implements AsyncUseCase<ApproveTeamJoinRequestCommandDTO, void, string> {
implements AsyncUseCase<ApproveTeamJoinRequestInputPort, void, string> {
constructor(
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 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 { ITeamRepository } from '../../domain/repositories/ITeamRepository';
import type {
TeamMembership,
TeamMembershipStatus,
TeamRole,
} from '../../domain/types/TeamMembership';
import type { JoinTeamCommandDTO } from '../dtos/JoinTeamCommandDTO';
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 { JoinTeamInputPort } from '../ports/input/JoinTeamInputPort';
type JoinTeamErrorCode = 'ALREADY_IN_TEAM' | 'ALREADY_MEMBER' | 'TEAM_NOT_FOUND' | 'REPOSITORY_ERROR';
type JoinTeamApplicationError = ApplicationErrorCode<JoinTeamErrorCode, { message: string }>;
export class JoinTeamUseCase implements AsyncUseCase<JoinTeamCommandDTO, void, JoinTeamErrorCode> {
export class JoinTeamUseCase implements AsyncUseCase<JoinTeamInputPort, void, JoinTeamErrorCode> {
constructor(
private readonly teamRepository: ITeamRepository,
private readonly membershipRepository: ITeamMembershipRepository,
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 });
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 { 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 { LeaveTeamInputPort } from '../ports/input/LeaveTeamInputPort';
type LeaveTeamErrorCode = 'NOT_MEMBER' | 'OWNER_CANNOT_LEAVE' | 'REPOSITORY_ERROR';
type LeaveTeamApplicationError = ApplicationErrorCode<LeaveTeamErrorCode, { message: string }>;
export class LeaveTeamUseCase implements AsyncUseCase<LeaveTeamCommandDTO, void, LeaveTeamErrorCode> {
export class LeaveTeamUseCase implements AsyncUseCase<LeaveTeamInputPort, void, LeaveTeamErrorCode> {
constructor(
private readonly membershipRepository: ITeamMembershipRepository,
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 });
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 type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository';
import type { RejectTeamJoinRequestInputPort } from '../ports/input/RejectTeamJoinRequestInputPort';
export class RejectTeamJoinRequestUseCase {
constructor(
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;
await this.membershipRepository.removeJoinRequest(requestId);
return Result.ok(undefined);

View File

@@ -1,9 +1,9 @@
import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { ITeamRepository } from '../../domain/repositories/ITeamRepository';
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';
@@ -13,7 +13,7 @@ export class UpdateTeamUseCase {
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 updaterMembership = await this.membershipRepository.getMembership(teamId, updatedBy);