133 lines
2.8 KiB
TypeScript
133 lines
2.8 KiB
TypeScript
export enum BlogPostStatus {
|
|
DRAFT = 'draft',
|
|
PUBLISHED = 'published',
|
|
ARCHIVED = 'archived',
|
|
}
|
|
|
|
export type BlogPostCategory = 'industry' | 'technology' | 'guides' | 'news';
|
|
|
|
interface BlogPostProps {
|
|
id: string;
|
|
title: string;
|
|
slug: string;
|
|
excerpt: string;
|
|
content: string;
|
|
coverImageUrl?: string;
|
|
category: BlogPostCategory;
|
|
tags: string[];
|
|
authorName: string;
|
|
status: BlogPostStatus;
|
|
isFeatured: boolean;
|
|
publishedAt?: Date;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
}
|
|
|
|
export class BlogPost {
|
|
private constructor(private readonly props: BlogPostProps) {}
|
|
|
|
static create(
|
|
props: Omit<BlogPostProps, 'status' | 'isFeatured' | 'publishedAt' | 'createdAt' | 'updatedAt'>
|
|
): BlogPost {
|
|
const now = new Date();
|
|
return new BlogPost({
|
|
...props,
|
|
status: BlogPostStatus.DRAFT,
|
|
isFeatured: false,
|
|
createdAt: now,
|
|
updatedAt: now,
|
|
});
|
|
}
|
|
|
|
static fromPersistence(props: BlogPostProps): BlogPost {
|
|
return new BlogPost(props);
|
|
}
|
|
|
|
get id(): string {
|
|
return this.props.id;
|
|
}
|
|
get title(): string {
|
|
return this.props.title;
|
|
}
|
|
get slug(): string {
|
|
return this.props.slug;
|
|
}
|
|
get excerpt(): string {
|
|
return this.props.excerpt;
|
|
}
|
|
get content(): string {
|
|
return this.props.content;
|
|
}
|
|
get coverImageUrl(): string | undefined {
|
|
return this.props.coverImageUrl;
|
|
}
|
|
get category(): BlogPostCategory {
|
|
return this.props.category;
|
|
}
|
|
get tags(): string[] {
|
|
return this.props.tags;
|
|
}
|
|
get authorName(): string {
|
|
return this.props.authorName;
|
|
}
|
|
get status(): BlogPostStatus {
|
|
return this.props.status;
|
|
}
|
|
get isFeatured(): boolean {
|
|
return this.props.isFeatured;
|
|
}
|
|
get publishedAt(): Date | undefined {
|
|
return this.props.publishedAt;
|
|
}
|
|
get createdAt(): Date {
|
|
return this.props.createdAt;
|
|
}
|
|
get updatedAt(): Date {
|
|
return this.props.updatedAt;
|
|
}
|
|
|
|
update(
|
|
data: Partial<
|
|
Pick<
|
|
BlogPostProps,
|
|
| 'title'
|
|
| 'slug'
|
|
| 'excerpt'
|
|
| 'content'
|
|
| 'coverImageUrl'
|
|
| 'category'
|
|
| 'tags'
|
|
| 'authorName'
|
|
| 'isFeatured'
|
|
>
|
|
>
|
|
): BlogPost {
|
|
return new BlogPost({ ...this.props, ...data, updatedAt: new Date() });
|
|
}
|
|
|
|
publish(): BlogPost {
|
|
return new BlogPost({
|
|
...this.props,
|
|
status: BlogPostStatus.PUBLISHED,
|
|
publishedAt: this.props.publishedAt ?? new Date(),
|
|
updatedAt: new Date(),
|
|
});
|
|
}
|
|
|
|
archive(): BlogPost {
|
|
return new BlogPost({ ...this.props, status: BlogPostStatus.ARCHIVED, updatedAt: new Date() });
|
|
}
|
|
|
|
unpublish(): BlogPost {
|
|
return new BlogPost({ ...this.props, status: BlogPostStatus.DRAFT, updatedAt: new Date() });
|
|
}
|
|
|
|
isPublished(): boolean {
|
|
return this.props.status === BlogPostStatus.PUBLISHED;
|
|
}
|
|
|
|
toObject(): BlogPostProps {
|
|
return { ...this.props };
|
|
}
|
|
}
|