99 lines
2.2 KiB
TypeScript
99 lines
2.2 KiB
TypeScript
/**
|
|
* Domain Entity: Driver
|
|
*
|
|
* Represents a driver profile in the GridPilot platform.
|
|
* Immutable entity with factory methods and domain validation.
|
|
*/
|
|
|
|
export class Driver {
|
|
readonly id: string;
|
|
readonly iracingId: string;
|
|
readonly name: string;
|
|
readonly country: string;
|
|
readonly bio?: string;
|
|
readonly joinedAt: Date;
|
|
|
|
private constructor(props: {
|
|
id: string;
|
|
iracingId: string;
|
|
name: string;
|
|
country: string;
|
|
bio?: string;
|
|
joinedAt: Date;
|
|
}) {
|
|
this.id = props.id;
|
|
this.iracingId = props.iracingId;
|
|
this.name = props.name;
|
|
this.country = props.country;
|
|
this.bio = props.bio;
|
|
this.joinedAt = props.joinedAt;
|
|
}
|
|
|
|
/**
|
|
* Factory method to create a new Driver entity
|
|
*/
|
|
static create(props: {
|
|
id: string;
|
|
iracingId: string;
|
|
name: string;
|
|
country: string;
|
|
bio?: string;
|
|
joinedAt?: Date;
|
|
}): Driver {
|
|
this.validate(props);
|
|
|
|
return new Driver({
|
|
...props,
|
|
joinedAt: props.joinedAt ?? new Date(),
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Domain validation logic
|
|
*/
|
|
private static validate(props: {
|
|
id: string;
|
|
iracingId: string;
|
|
name: string;
|
|
country: string;
|
|
}): void {
|
|
if (!props.id || props.id.trim().length === 0) {
|
|
throw new Error('Driver ID is required');
|
|
}
|
|
|
|
if (!props.iracingId || props.iracingId.trim().length === 0) {
|
|
throw new Error('iRacing ID is required');
|
|
}
|
|
|
|
if (!props.name || props.name.trim().length === 0) {
|
|
throw new Error('Driver name is required');
|
|
}
|
|
|
|
if (!props.country || props.country.trim().length === 0) {
|
|
throw new Error('Country code is required');
|
|
}
|
|
|
|
// Validate ISO country code format (2-3 letters)
|
|
if (!/^[A-Z]{2,3}$/i.test(props.country)) {
|
|
throw new Error('Country must be a valid ISO code (2-3 letters)');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a copy with updated properties
|
|
*/
|
|
update(props: Partial<{
|
|
name: string;
|
|
country: string;
|
|
bio: string;
|
|
}>): Driver {
|
|
return new Driver({
|
|
id: this.id,
|
|
iracingId: this.iracingId,
|
|
name: props.name ?? this.name,
|
|
country: props.country ?? this.country,
|
|
bio: props.bio ?? this.bio,
|
|
joinedAt: this.joinedAt,
|
|
});
|
|
}
|
|
} |