refactor
This commit is contained in:
86
core/racing/domain/entities/sponsor/Sponsor.ts
Normal file
86
core/racing/domain/entities/sponsor/Sponsor.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Domain Entity: Sponsor
|
||||
*
|
||||
* Represents a sponsor that can sponsor leagues/seasons.
|
||||
* Aggregate root for sponsor information.
|
||||
*/
|
||||
import type { IEntity } from '@core/shared/domain';
|
||||
import { SponsorId } from './SponsorId';
|
||||
import { SponsorName } from './SponsorName';
|
||||
import { SponsorEmail } from './SponsorEmail';
|
||||
import { Url } from './Url';
|
||||
import { SponsorCreatedAt } from './SponsorCreatedAt';
|
||||
|
||||
export class Sponsor implements IEntity<SponsorId> {
|
||||
readonly id: SponsorId;
|
||||
readonly name: SponsorName;
|
||||
readonly contactEmail: SponsorEmail;
|
||||
readonly logoUrl: Url | undefined;
|
||||
readonly websiteUrl: Url | undefined;
|
||||
readonly createdAt: SponsorCreatedAt;
|
||||
|
||||
private constructor(props: {
|
||||
id: SponsorId;
|
||||
name: SponsorName;
|
||||
contactEmail: SponsorEmail;
|
||||
logoUrl?: Url;
|
||||
websiteUrl?: Url;
|
||||
createdAt: SponsorCreatedAt;
|
||||
}) {
|
||||
this.id = props.id;
|
||||
this.name = props.name;
|
||||
this.contactEmail = props.contactEmail;
|
||||
this.logoUrl = props.logoUrl;
|
||||
this.websiteUrl = props.websiteUrl;
|
||||
this.createdAt = props.createdAt;
|
||||
}
|
||||
|
||||
static create(props: {
|
||||
id: string;
|
||||
name: string;
|
||||
contactEmail: string;
|
||||
logoUrl?: string;
|
||||
websiteUrl?: string;
|
||||
createdAt?: Date;
|
||||
}): Sponsor {
|
||||
const id = SponsorId.create(props.id);
|
||||
const name = SponsorName.create(props.name);
|
||||
const contactEmail = SponsorEmail.create(props.contactEmail);
|
||||
const logoUrl = props.logoUrl ? Url.create(props.logoUrl) : undefined;
|
||||
const websiteUrl = props.websiteUrl ? Url.create(props.websiteUrl) : undefined;
|
||||
const createdAt = SponsorCreatedAt.create(props.createdAt ?? new Date());
|
||||
|
||||
return new Sponsor({
|
||||
id,
|
||||
name,
|
||||
contactEmail,
|
||||
createdAt,
|
||||
...(logoUrl !== undefined ? { logoUrl } : {}),
|
||||
...(websiteUrl !== undefined ? { websiteUrl } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update sponsor information
|
||||
*/
|
||||
update(props: Partial<{
|
||||
name: string;
|
||||
contactEmail: string;
|
||||
logoUrl?: string;
|
||||
websiteUrl?: string;
|
||||
}>): Sponsor {
|
||||
const name = props.name ? SponsorName.create(props.name) : this.name;
|
||||
const contactEmail = props.contactEmail ? SponsorEmail.create(props.contactEmail) : this.contactEmail;
|
||||
const logoUrl = props.logoUrl !== undefined ? (props.logoUrl ? Url.create(props.logoUrl) : undefined) : this.logoUrl;
|
||||
const websiteUrl = props.websiteUrl !== undefined ? (props.websiteUrl ? Url.create(props.websiteUrl) : undefined) : this.websiteUrl;
|
||||
|
||||
return new Sponsor({
|
||||
id: this.id,
|
||||
name,
|
||||
contactEmail,
|
||||
logoUrl,
|
||||
websiteUrl,
|
||||
createdAt: this.createdAt,
|
||||
});
|
||||
}
|
||||
}
|
||||
21
core/racing/domain/entities/sponsor/SponsorCreatedAt.ts
Normal file
21
core/racing/domain/entities/sponsor/SponsorCreatedAt.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { RacingDomainValidationError } from '../../errors/RacingDomainError';
|
||||
|
||||
export class SponsorCreatedAt {
|
||||
private constructor(private readonly value: Date) {}
|
||||
|
||||
static create(value: Date): SponsorCreatedAt {
|
||||
const now = new Date();
|
||||
if (value > now) {
|
||||
throw new RacingDomainValidationError('Created date cannot be in the future');
|
||||
}
|
||||
return new SponsorCreatedAt(new Date(value));
|
||||
}
|
||||
|
||||
toDate(): Date {
|
||||
return new Date(this.value);
|
||||
}
|
||||
|
||||
equals(other: SponsorCreatedAt): boolean {
|
||||
return this.value.getTime() === other.value.getTime();
|
||||
}
|
||||
}
|
||||
24
core/racing/domain/entities/sponsor/SponsorEmail.ts
Normal file
24
core/racing/domain/entities/sponsor/SponsorEmail.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { RacingDomainValidationError } from '../../errors/RacingDomainError';
|
||||
|
||||
export class SponsorEmail {
|
||||
private constructor(private readonly value: string) {}
|
||||
|
||||
static create(value: string): SponsorEmail {
|
||||
if (!value || value.trim().length === 0) {
|
||||
throw new RacingDomainValidationError('Sponsor contact email cannot be empty');
|
||||
}
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(value)) {
|
||||
throw new RacingDomainValidationError('Invalid sponsor contact email format');
|
||||
}
|
||||
return new SponsorEmail(value.trim());
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
equals(other: SponsorEmail): boolean {
|
||||
return this.value === other.value;
|
||||
}
|
||||
}
|
||||
20
core/racing/domain/entities/sponsor/SponsorId.ts
Normal file
20
core/racing/domain/entities/sponsor/SponsorId.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { RacingDomainValidationError } from '../../errors/RacingDomainError';
|
||||
|
||||
export class SponsorId {
|
||||
private constructor(private readonly value: string) {}
|
||||
|
||||
static create(value: string): SponsorId {
|
||||
if (!value || value.trim().length === 0) {
|
||||
throw new RacingDomainValidationError('Sponsor ID cannot be empty');
|
||||
}
|
||||
return new SponsorId(value.trim());
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
equals(other: SponsorId): boolean {
|
||||
return this.value === other.value;
|
||||
}
|
||||
}
|
||||
23
core/racing/domain/entities/sponsor/SponsorName.ts
Normal file
23
core/racing/domain/entities/sponsor/SponsorName.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { RacingDomainValidationError } from '../../errors/RacingDomainError';
|
||||
|
||||
export class SponsorName {
|
||||
private constructor(private readonly value: string) {}
|
||||
|
||||
static create(value: string): SponsorName {
|
||||
if (!value || value.trim().length === 0) {
|
||||
throw new RacingDomainValidationError('Sponsor name cannot be empty');
|
||||
}
|
||||
if (value.length > 100) {
|
||||
throw new RacingDomainValidationError('Sponsor name cannot exceed 100 characters');
|
||||
}
|
||||
return new SponsorName(value.trim());
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
equals(other: SponsorName): boolean {
|
||||
return this.value === other.value;
|
||||
}
|
||||
}
|
||||
25
core/racing/domain/entities/sponsor/Url.ts
Normal file
25
core/racing/domain/entities/sponsor/Url.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { RacingDomainValidationError } from '../../errors/RacingDomainError';
|
||||
|
||||
export class Url {
|
||||
private constructor(private readonly value: string) {}
|
||||
|
||||
static create(value: string): Url {
|
||||
if (!value || value.trim().length === 0) {
|
||||
throw new RacingDomainValidationError('URL cannot be empty');
|
||||
}
|
||||
try {
|
||||
new URL(value);
|
||||
} catch {
|
||||
throw new RacingDomainValidationError('Invalid URL format');
|
||||
}
|
||||
return new Url(value.trim());
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
equals(other: Url): boolean {
|
||||
return this.value === other.value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user