Files
gridpilot.gg/packages/racing/application/use-cases/JoinLeagueUseCase.ts
2025-12-14 18:11:59 +01:00

55 lines
2.1 KiB
TypeScript

import type { ILogger } from '../../../shared/src/logging/ILogger';
import type {
ILeagueMembershipRepository,
} from '@gridpilot/racing/domain/repositories/ILeagueMembershipRepository';
import type { AsyncUseCase } from '@gridpilot/shared/application';
import {
LeagueMembership,
type MembershipRole,
type MembershipStatus,
} from '@gridpilot/racing/domain/entities/LeagueMembership';
import type { JoinLeagueCommandDTO } from '../dto/JoinLeagueCommandDTO';
import { BusinessRuleViolationError } from '../errors/RacingApplicationError';
export class JoinLeagueUseCase implements AsyncUseCase<JoinLeagueCommandDTO, LeagueMembership> {
constructor(
private readonly membershipRepository: ILeagueMembershipRepository,
private readonly logger: ILogger,
) {}
/**
* Joins a driver to a league as an active member.
*
* Mirrors the behavior of the legacy joinLeague function:
* - Throws when membership already exists for this league/driver.
* - Creates a new active membership with role "member" and current timestamp.
*/
async execute(command: JoinLeagueCommandDTO): Promise<LeagueMembership> {
this.logger.debug('Attempting to join league', { command });
const { leagueId, driverId } = command;
try {
const existing = await this.membershipRepository.getMembership(leagueId, driverId);
if (existing) {
this.logger.warn('Driver already a member or has pending request', { leagueId, driverId });
throw new BusinessRuleViolationError('Already a member or have a pending request');
}
const membership = LeagueMembership.create({
leagueId,
driverId,
role: 'member' as MembershipRole,
status: 'active' as MembershipStatus,
});
const savedMembership = await this.membershipRepository.saveMembership(membership);
this.logger.info('Successfully joined league', { membershipId: savedMembership.id });
return savedMembership;
} catch (error) {
if (!(error instanceof BusinessRuleViolationError)) {
this.logger.error('Failed to join league due to an unexpected error', { command, error: error.message });
}
throw error;
}
}
}