/** * Domain Entity: Team * * Represents a racing team in the GridPilot platform. * Implements the shared Entity contract and encapsulates * basic invariants around identity and core properties. */ import { MediaReference } from '@core/domain/media/MediaReference'; import { Entity } from '@core/shared/domain/Entity'; import { RacingDomainValidationError } from '../errors/RacingDomainError'; import { TeamCreatedAt } from '../value-objects/TeamCreatedAt'; import { TeamDescription } from '../value-objects/TeamDescription'; import { TeamName } from '../value-objects/TeamName'; import { TeamTag } from '../value-objects/TeamTag'; import { DriverId } from './DriverId'; import { LeagueId } from './LeagueId'; export class Team extends Entity { readonly name: TeamName; readonly tag: TeamTag; readonly description: TeamDescription; readonly ownerId: DriverId; readonly leagues: LeagueId[]; readonly category: string | undefined; readonly isRecruiting: boolean; readonly createdAt: TeamCreatedAt; readonly logoRef: MediaReference; private constructor(props: { id: string; name: TeamName; tag: TeamTag; description: TeamDescription; ownerId: DriverId; leagues: LeagueId[]; category: string | undefined; isRecruiting: boolean; createdAt: TeamCreatedAt; logoRef: MediaReference; }) { super(props.id); this.name = props.name; this.tag = props.tag; this.description = props.description; this.ownerId = props.ownerId; this.leagues = props.leagues; this.category = props.category; this.isRecruiting = props.isRecruiting; this.createdAt = props.createdAt; this.logoRef = props.logoRef; } /** * Factory method to create a new Team entity. */ static create(props: { id: string; name: string; tag: string; description: string; ownerId: string; leagues: string[]; category?: string; isRecruiting?: boolean; createdAt?: Date; logoRef?: MediaReference; }): Team { if (!props.id || props.id.trim().length === 0) { throw new RacingDomainValidationError('Team ID is required'); } if (!Array.isArray(props.leagues)) { throw new RacingDomainValidationError('Team leagues must be an array'); } return new Team({ id: props.id, name: TeamName.create(props.name), tag: TeamTag.create(props.tag), description: TeamDescription.create(props.description), ownerId: DriverId.create(props.ownerId), leagues: props.leagues.map(leagueId => LeagueId.create(leagueId)), category: props.category, isRecruiting: props.isRecruiting ?? false, createdAt: TeamCreatedAt.create(props.createdAt ?? new Date()), logoRef: props.logoRef ?? MediaReference.createSystemDefault('logo'), }); } static rehydrate(props: { id: string; name: string; tag: string; description: string; ownerId: string; leagues: string[]; category?: string; isRecruiting: boolean; createdAt: Date; logoRef?: MediaReference; }): Team { if (!props.id || props.id.trim().length === 0) { throw new RacingDomainValidationError('Team ID is required'); } if (!Array.isArray(props.leagues)) { throw new RacingDomainValidationError('Team leagues must be an array'); } return new Team({ id: props.id, name: TeamName.create(props.name), tag: TeamTag.create(props.tag), description: TeamDescription.create(props.description), ownerId: DriverId.create(props.ownerId), leagues: props.leagues.map(leagueId => LeagueId.create(leagueId)), category: props.category, isRecruiting: props.isRecruiting, createdAt: TeamCreatedAt.create(props.createdAt), logoRef: props.logoRef ?? MediaReference.createSystemDefault('logo'), }); } /** * Create a copy with updated properties. */ update(props: Partial<{ name: string; tag: string; description: string; ownerId: string; leagues: string[]; category: string | undefined; isRecruiting: boolean; logoRef: MediaReference; }>): Team { const nextName = 'name' in props ? TeamName.create(props.name!) : this.name; const nextTag = 'tag' in props ? TeamTag.create(props.tag!) : this.tag; const nextDescription = 'description' in props ? TeamDescription.create(props.description!) : this.description; const nextOwnerId = 'ownerId' in props ? DriverId.create(props.ownerId!) : this.ownerId; const nextLeagues = 'leagues' in props ? props.leagues!.map(leagueId => LeagueId.create(leagueId)) : this.leagues; const nextCategory = 'category' in props ? props.category : this.category; const nextIsRecruiting = 'isRecruiting' in props ? props.isRecruiting! : this.isRecruiting; const nextLogoRef = 'logoRef' in props ? props.logoRef! : this.logoRef; return new Team({ id: this.id, name: nextName, tag: nextTag, description: nextDescription, ownerId: nextOwnerId, leagues: nextLeagues, category: nextCategory, isRecruiting: nextIsRecruiting, createdAt: this.createdAt, logoRef: nextLogoRef, }); } equals(other: Entity): boolean { if (!(other instanceof Team)) { return false; } return this.id === other.id; } }