Files
gridpilot.gg/core/racing/application/use-cases/LeaveTeamUseCase.ts
2026-01-16 19:46:49 +01:00

98 lines
2.9 KiB
TypeScript

import type { Logger } from '@core/shared/domain/Logger';
import { Result } from '@core/shared/domain/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { Team } from '../../domain/entities/Team';
import { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
import { TeamRepository } from '../../domain/repositories/TeamRepository';
import { TeamMembership } from '../../domain/types/TeamMembership';
export type LeaveTeamErrorCode =
| 'TEAM_NOT_FOUND'
| 'NOT_MEMBER'
| 'OWNER_CANNOT_LEAVE'
| 'REPOSITORY_ERROR';
export type LeaveTeamInput = {
teamId: string;
driverId: string;
};
export interface LeaveTeamResult {
team: Team;
previousMembership: TeamMembership;
}
export class LeaveTeamUseCase {
constructor(
private readonly teamRepository: TeamRepository,
private readonly membershipRepository: TeamMembershipRepository,
private readonly logger: Logger,
) {}
async execute(
input: LeaveTeamInput,
): Promise<
Result<LeaveTeamResult, ApplicationErrorCode<LeaveTeamErrorCode, { message: string }>>
> {
this.logger.debug('Attempting to leave team', { input });
const { teamId, driverId } = input;
try {
const team = await this.teamRepository.findById(teamId);
if (!team) {
const error = new Error(`Team ${teamId} not found`);
this.logger.error('Team not found', error);
return Result.err({
code: 'TEAM_NOT_FOUND',
details: { message: `Team ${teamId} not found` },
});
}
const membership = await this.membershipRepository.getMembership(
teamId,
driverId,
);
if (!membership) {
this.logger.warn('Driver is not a member of this team', {
driverId,
teamId,
});
return Result.err({
code: 'NOT_MEMBER',
details: { message: 'Not a member of this team' },
});
}
if (membership.role === 'owner') {
this.logger.warn('Team owner cannot leave', { driverId, teamId });
return Result.err({
code: 'OWNER_CANNOT_LEAVE',
details: {
message:
'Team owner cannot leave. Transfer ownership or disband team first.',
},
});
}
await this.membershipRepository.removeMembership(teamId, driverId);
this.logger.info('Driver successfully left team', { driverId, teamId });
const result: LeaveTeamResult = {
team,
previousMembership: membership,
};
return Result.ok(result);
} catch (error) {
this.logger.error(
'Failed to leave team due to an unexpected error',
error instanceof Error ? error : new Error('Unknown error'),
);
return Result.err({
code: 'REPOSITORY_ERROR',
details: {
message: error instanceof Error ? error.message : 'Unknown error',
},
});
}
}
}