diff --git a/packages/core/src/application/use-cases/content/create-article.use-case.ts b/packages/core/src/application/use-cases/content/create-article.use-case.ts new file mode 100644 index 0000000..64985c8 --- /dev/null +++ b/packages/core/src/application/use-cases/content/create-article.use-case.ts @@ -0,0 +1,32 @@ +import type { Article } from "@/entities/models/article.js"; +import { getInjection } from "@/di/container.js"; + +function generateSlug(title: string): string { + return title + .toLowerCase() + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-|-$/g, ""); +} + +export async function createArticleUseCase(input: { + title: string; + content: string; + authorId: string; + slug?: string; +}): Promise
{ + const articlesRepository = getInjection("IArticlesRepository"); + + const now = new Date(); + const article: Article = { + id: crypto.randomUUID(), + title: input.title, + slug: input.slug ?? generateSlug(input.title), + content: input.content, + status: "draft", + authorId: input.authorId, + createdAt: now, + updatedAt: now, + }; + + return await articlesRepository.createArticle(article); +} diff --git a/packages/core/src/application/use-cases/content/get-articles.use-case.ts b/packages/core/src/application/use-cases/content/get-articles.use-case.ts new file mode 100644 index 0000000..6094d69 --- /dev/null +++ b/packages/core/src/application/use-cases/content/get-articles.use-case.ts @@ -0,0 +1,12 @@ +import type { Article } from "@/entities/models/article.js"; +import { getInjection } from "@/di/container.js"; + +export async function getArticlesUseCase(options?: { + status?: string; + authorId?: string; + limit?: number; + offset?: number; +}): Promise { + const articlesRepository = getInjection("IArticlesRepository"); + return await articlesRepository.getArticles(options); +} diff --git a/packages/core/tests/unit/use-cases/content/create-article.use-case.test.ts b/packages/core/tests/unit/use-cases/content/create-article.use-case.test.ts new file mode 100644 index 0000000..3f09844 --- /dev/null +++ b/packages/core/tests/unit/use-cases/content/create-article.use-case.test.ts @@ -0,0 +1,41 @@ +import "reflect-metadata"; +import { afterEach, beforeEach, describe, expect, it } from "vitest"; + +import { + destroyContainer, + initializeContainer, +} from "@/di/container.js"; +import { createArticleUseCase } from "@/application/use-cases/content/create-article.use-case.js"; + +beforeEach(() => { + initializeContainer(); +}); + +afterEach(() => { + destroyContainer(); +}); + +describe("createArticleUseCase", () => { + it("creates an article with generated slug and draft status", async () => { + const result = await createArticleUseCase({ + title: "My First Article", + content: "Hello world", + authorId: "1", + }); + expect(result.title).toBe("My First Article"); + expect(result.slug).toBe("my-first-article"); + expect(result.status).toBe("draft"); + expect(result.authorId).toBe("1"); + expect(result.id).toBeDefined(); + }); + + it("uses provided slug if given", async () => { + const result = await createArticleUseCase({ + title: "Another Article", + content: "Content here", + authorId: "1", + slug: "custom-slug", + }); + expect(result.slug).toBe("custom-slug"); + }); +}); diff --git a/packages/core/tests/unit/use-cases/content/get-articles.use-case.test.ts b/packages/core/tests/unit/use-cases/content/get-articles.use-case.test.ts new file mode 100644 index 0000000..aed1bd5 --- /dev/null +++ b/packages/core/tests/unit/use-cases/content/get-articles.use-case.test.ts @@ -0,0 +1,51 @@ +import "reflect-metadata"; +import { afterEach, beforeEach, describe, expect, it } from "vitest"; + +import { + destroyContainer, + initializeContainer, +} from "@/di/container.js"; +import { createArticleUseCase } from "@/application/use-cases/content/create-article.use-case.js"; +import { getArticlesUseCase } from "@/application/use-cases/content/get-articles.use-case.js"; + +beforeEach(() => { + initializeContainer(); +}); + +afterEach(() => { + destroyContainer(); +}); + +describe("getArticlesUseCase", () => { + it("returns empty array when no articles exist", async () => { + const result = await getArticlesUseCase(); + expect(result).toEqual([]); + }); + + it("returns created articles", async () => { + await createArticleUseCase({ + title: "Article One", + content: "Content one", + authorId: "1", + }); + await createArticleUseCase({ + title: "Article Two", + content: "Content two", + authorId: "1", + }); + + const result = await getArticlesUseCase(); + expect(result).toHaveLength(2); + }); + + it("filters by status", async () => { + await createArticleUseCase({ + title: "Draft Article", + content: "Draft", + authorId: "1", + }); + + const result = await getArticlesUseCase({ status: "published" }); + expect(result).toHaveLength(0); + }); +});