180 lines
4.0 KiB
TypeScript
180 lines
4.0 KiB
TypeScript
export enum BlogPostStatus {
|
|
DRAFT = 'draft',
|
|
SCHEDULED = 'scheduled',
|
|
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;
|
|
metaTitle?: string;
|
|
metaDescription?: string;
|
|
primaryKeyword?: string;
|
|
secondaryKeywords: string[];
|
|
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,
|
|
secondaryKeywords: props.secondaryKeywords ?? [],
|
|
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 metaTitle(): string | undefined {
|
|
return this.props.metaTitle;
|
|
}
|
|
get metaDescription(): string | undefined {
|
|
return this.props.metaDescription;
|
|
}
|
|
get primaryKeyword(): string | undefined {
|
|
return this.props.primaryKeyword;
|
|
}
|
|
get secondaryKeywords(): string[] {
|
|
return this.props.secondaryKeywords;
|
|
}
|
|
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'
|
|
| 'metaTitle'
|
|
| 'metaDescription'
|
|
| 'primaryKeyword'
|
|
| 'secondaryKeywords'
|
|
>
|
|
>
|
|
): 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(),
|
|
});
|
|
}
|
|
|
|
schedule(date: Date): BlogPost {
|
|
return new BlogPost({
|
|
...this.props,
|
|
status: BlogPostStatus.SCHEDULED,
|
|
publishedAt: 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,
|
|
publishedAt: undefined,
|
|
updatedAt: new Date(),
|
|
});
|
|
}
|
|
|
|
isPublished(): boolean {
|
|
return this.props.status === BlogPostStatus.PUBLISHED;
|
|
}
|
|
|
|
isVisibleToPublic(): boolean {
|
|
if (this.props.status === BlogPostStatus.PUBLISHED) return true;
|
|
if (
|
|
this.props.status === BlogPostStatus.SCHEDULED &&
|
|
this.props.publishedAt &&
|
|
this.props.publishedAt <= new Date()
|
|
)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
toObject(): BlogPostProps {
|
|
return { ...this.props };
|
|
}
|
|
}
|