Files
gridpilot.gg/core/racing/domain/entities/LeagueMembership.ts
2026-01-16 16:46:57 +01:00

114 lines
3.1 KiB
TypeScript

/**
* Domain Entity: LeagueMembership
*
* Represents a driver's membership in a league.
*/
import { Entity } from '@core/shared/domain/Entity';
import { RacingDomainValidationError } from '../errors/RacingDomainError';
import { JoinedAt } from '../value-objects/JoinedAt';
import { DriverId } from './DriverId';
import { JoinRequest } from './JoinRequest';
import { LeagueId } from './LeagueId';
import { MembershipRole, MembershipRoleValue } from './MembershipRole';
import { MembershipStatus, MembershipStatusValue } from './MembershipStatus';
export interface LeagueMembershipProps {
id?: string;
leagueId: string;
driverId: string;
role: string;
status?: string;
joinedAt?: Date;
}
export class LeagueMembership extends Entity<string> {
readonly leagueId: LeagueId;
readonly driverId: DriverId;
readonly role: MembershipRole;
readonly status: MembershipStatus;
readonly joinedAt: JoinedAt;
private constructor(props: {
id: string;
leagueId: LeagueId;
driverId: DriverId;
role: MembershipRole;
status: MembershipStatus;
joinedAt: JoinedAt;
}) {
super(props.id);
this.leagueId = props.leagueId;
this.driverId = props.driverId;
this.role = props.role;
this.status = props.status;
this.joinedAt = props.joinedAt;
}
static create(props: LeagueMembershipProps): LeagueMembership {
this.validate(props);
const id =
props.id && props.id.trim().length > 0
? props.id
: `${props.leagueId}:${props.driverId}`;
const leagueId = LeagueId.create(props.leagueId);
const driverId = DriverId.create(props.driverId);
const role = MembershipRole.create(props.role as MembershipRoleValue);
const status = MembershipStatus.create((props.status ?? 'pending') as MembershipStatusValue);
const joinedAt = JoinedAt.create(props.joinedAt ?? new Date());
return new LeagueMembership({
id,
leagueId,
driverId,
role,
status,
joinedAt,
});
}
static rehydrate(props: {
id: string;
leagueId: string;
driverId: string;
role: MembershipRoleValue;
status: MembershipStatusValue;
joinedAt: Date;
}): LeagueMembership {
return new LeagueMembership({
id: props.id,
leagueId: LeagueId.create(props.leagueId),
driverId: DriverId.create(props.driverId),
role: MembershipRole.create(props.role),
status: MembershipStatus.create(props.status),
joinedAt: JoinedAt.create(props.joinedAt),
});
}
private static validate(props: LeagueMembershipProps): void {
if (!props.leagueId || props.leagueId.trim().length === 0) {
throw new RacingDomainValidationError('League ID is required');
}
if (!props.driverId || props.driverId.trim().length === 0) {
throw new RacingDomainValidationError('Driver ID is required');
}
if (!props.role) {
throw new RacingDomainValidationError('Membership role is required');
}
}
equals(other: Entity<string>): boolean {
if (!(other instanceof LeagueMembership)) {
return false;
}
return this.id === other.id;
}
}
export { JoinRequest, MembershipRole, MembershipStatus };