wip
This commit is contained in:
@@ -1,35 +1,128 @@
|
||||
/**
|
||||
* Domain Entities: Team, TeamMembership, TeamJoinRequest
|
||||
* Domain Entity: Team
|
||||
*
|
||||
* Extracted from racing-application teams module so that
|
||||
* team-related types live in the racing-domain package.
|
||||
* Represents a racing team in the GridPilot platform.
|
||||
* Implements the shared IEntity<string> contract and encapsulates
|
||||
* basic invariants around identity and core properties.
|
||||
*/
|
||||
|
||||
export type TeamRole = 'owner' | 'manager' | 'driver';
|
||||
export type TeamMembershipStatus = 'active' | 'pending' | 'none';
|
||||
import type { IEntity } from '@gridpilot/shared/domain';
|
||||
import { RacingDomainValidationError } from '../errors/RacingDomainError';
|
||||
|
||||
export interface Team {
|
||||
id: string;
|
||||
name: string;
|
||||
tag: string;
|
||||
description: string;
|
||||
ownerId: string;
|
||||
leagues: string[];
|
||||
createdAt: Date;
|
||||
}
|
||||
export class Team implements IEntity<string> {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly tag: string;
|
||||
readonly description: string;
|
||||
readonly ownerId: string;
|
||||
readonly leagues: string[];
|
||||
readonly createdAt: Date;
|
||||
|
||||
export interface TeamMembership {
|
||||
teamId: string;
|
||||
driverId: string;
|
||||
role: TeamRole;
|
||||
status: TeamMembershipStatus;
|
||||
joinedAt: Date;
|
||||
}
|
||||
private constructor(props: {
|
||||
id: string;
|
||||
name: string;
|
||||
tag: string;
|
||||
description: string;
|
||||
ownerId: string;
|
||||
leagues: string[];
|
||||
createdAt: Date;
|
||||
}) {
|
||||
this.id = props.id;
|
||||
this.name = props.name;
|
||||
this.tag = props.tag;
|
||||
this.description = props.description;
|
||||
this.ownerId = props.ownerId;
|
||||
this.leagues = props.leagues;
|
||||
this.createdAt = props.createdAt;
|
||||
}
|
||||
|
||||
export interface TeamJoinRequest {
|
||||
id: string;
|
||||
teamId: string;
|
||||
driverId: string;
|
||||
requestedAt: Date;
|
||||
message?: string;
|
||||
/**
|
||||
* Factory method to create a new Team entity.
|
||||
*/
|
||||
static create(props: {
|
||||
id: string;
|
||||
name: string;
|
||||
tag: string;
|
||||
description: string;
|
||||
ownerId: string;
|
||||
leagues: string[];
|
||||
createdAt?: Date;
|
||||
}): Team {
|
||||
this.validate(props);
|
||||
|
||||
return new Team({
|
||||
id: props.id,
|
||||
name: props.name,
|
||||
tag: props.tag,
|
||||
description: props.description,
|
||||
ownerId: props.ownerId,
|
||||
leagues: [...props.leagues],
|
||||
createdAt: props.createdAt ?? new Date(),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy with updated properties.
|
||||
*/
|
||||
update(props: Partial<{
|
||||
name: string;
|
||||
tag: string;
|
||||
description: string;
|
||||
ownerId: string;
|
||||
leagues: string[];
|
||||
}>): Team {
|
||||
const next: Team = new Team({
|
||||
id: this.id,
|
||||
name: props.name ?? this.name,
|
||||
tag: props.tag ?? this.tag,
|
||||
description: props.description ?? this.description,
|
||||
ownerId: props.ownerId ?? this.ownerId,
|
||||
leagues: props.leagues ? [...props.leagues] : [...this.leagues],
|
||||
createdAt: this.createdAt,
|
||||
});
|
||||
|
||||
// Re-validate updated aggregate
|
||||
Team.validate({
|
||||
id: next.id,
|
||||
name: next.name,
|
||||
tag: next.tag,
|
||||
description: next.description,
|
||||
ownerId: next.ownerId,
|
||||
leagues: next.leagues,
|
||||
});
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Domain validation logic for core invariants.
|
||||
*/
|
||||
private static validate(props: {
|
||||
id: string;
|
||||
name: string;
|
||||
tag: string;
|
||||
description: string;
|
||||
ownerId: string;
|
||||
leagues: string[];
|
||||
}): void {
|
||||
if (!props.id || props.id.trim().length === 0) {
|
||||
throw new RacingDomainValidationError('Team ID is required');
|
||||
}
|
||||
|
||||
if (!props.name || props.name.trim().length === 0) {
|
||||
throw new RacingDomainValidationError('Team name is required');
|
||||
}
|
||||
|
||||
if (!props.tag || props.tag.trim().length === 0) {
|
||||
throw new RacingDomainValidationError('Team tag is required');
|
||||
}
|
||||
|
||||
if (!props.ownerId || props.ownerId.trim().length === 0) {
|
||||
throw new RacingDomainValidationError('Team owner ID is required');
|
||||
}
|
||||
|
||||
if (!Array.isArray(props.leagues)) {
|
||||
throw new RacingDomainValidationError('Team leagues must be an array');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user