refactor: strip Phase/Plan/R-number references from source comments
This commit is contained in:
@@ -76,9 +76,7 @@ export const articlesRepositoryContract =
|
||||
|
||||
it("getArticles filters by status", async () => {
|
||||
await repo.createArticle(articleFactory.build({ status: "draft" }));
|
||||
await repo.createArticle(
|
||||
articleFactory.build({ status: "published" }),
|
||||
);
|
||||
await repo.createArticle(articleFactory.build({ status: "published" }));
|
||||
const drafts = await repo.getArticles({ status: "draft" });
|
||||
expect(drafts).toHaveLength(1);
|
||||
expect(drafts[0]?.status).toBe("draft");
|
||||
@@ -117,7 +115,7 @@ export const articlesRepositoryContract =
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
describe("span emission (R50)", () => {
|
||||
describe("span emission", () => {
|
||||
it("getArticles emits articles.getArticles span with op=repository", async () => {
|
||||
if (!getTracer) return;
|
||||
const tracer = getTracer();
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { ZodError } from "zod";
|
||||
import { createArticleUseCase, createArticleOutputSchema } from "@/application/use-cases/create-article.use-case";
|
||||
import {
|
||||
createArticleUseCase,
|
||||
createArticleOutputSchema,
|
||||
} from "@/application/use-cases/create-article.use-case";
|
||||
import { MockArticlesRepository } from "@/infrastructure/repositories/articles.repository.mock";
|
||||
import type { IArticlesRepository } from "@/application/repositories/articles.repository.interface";
|
||||
|
||||
@@ -37,7 +40,7 @@ describe("createArticleUseCase", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("createArticleUseCase output validation (R25)", () => {
|
||||
describe("createArticleUseCase output validation", () => {
|
||||
it("throws when repository returns a malformed article", async () => {
|
||||
const repo = {
|
||||
createArticle: async () => ({ id: 1 }) as unknown as never,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { ZodError } from "zod";
|
||||
import { getArticleBySlugUseCase, getArticleBySlugOutputSchema } from "@/application/use-cases/get-article-by-slug.use-case";
|
||||
import {
|
||||
getArticleBySlugUseCase,
|
||||
getArticleBySlugOutputSchema,
|
||||
} from "@/application/use-cases/get-article-by-slug.use-case";
|
||||
import { MockArticlesRepository } from "@/infrastructure/repositories/articles.repository.mock";
|
||||
import { ArticleNotFoundError } from "@/entities/errors/article";
|
||||
import { articleFactory } from "@/__factories__/article.factory";
|
||||
@@ -21,11 +24,13 @@ describe("getArticleBySlugUseCase", () => {
|
||||
it("throws ArticleNotFoundError when slug is missing", async () => {
|
||||
const repo = new MockArticlesRepository();
|
||||
const useCase = getArticleBySlugUseCase(repo);
|
||||
await expect(useCase({ slug: "does-not-exist" })).rejects.toThrow(ArticleNotFoundError);
|
||||
await expect(useCase({ slug: "does-not-exist" })).rejects.toThrow(
|
||||
ArticleNotFoundError,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getArticleBySlugUseCase output validation (R25)", () => {
|
||||
describe("getArticleBySlugUseCase output validation", () => {
|
||||
it("throws when repository returns a malformed article", async () => {
|
||||
const repo = {
|
||||
getArticleBySlug: async () => ({ id: 123 }) as unknown as never,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { ZodError } from "zod";
|
||||
import { getArticlesUseCase, getArticlesOutputSchema } from "@/application/use-cases/get-articles.use-case";
|
||||
import {
|
||||
getArticlesUseCase,
|
||||
getArticlesOutputSchema,
|
||||
} from "@/application/use-cases/get-articles.use-case";
|
||||
import { MockArticlesRepository } from "@/infrastructure/repositories/articles.repository.mock";
|
||||
import { articleFactory } from "@/__factories__/article.factory";
|
||||
|
||||
@@ -8,7 +11,9 @@ describe("getArticlesUseCase", () => {
|
||||
it("returns all articles with no filters", async () => {
|
||||
const repo = new MockArticlesRepository();
|
||||
articleFactory.reset();
|
||||
await repo.createArticle(articleFactory.build({ id: "1", title: "A", slug: "a" }));
|
||||
await repo.createArticle(
|
||||
articleFactory.build({ id: "1", title: "A", slug: "a" }),
|
||||
);
|
||||
|
||||
const useCase = getArticlesUseCase(repo);
|
||||
const result = await useCase({});
|
||||
@@ -19,8 +24,17 @@ describe("getArticlesUseCase", () => {
|
||||
it("filters by status", async () => {
|
||||
const repo = new MockArticlesRepository();
|
||||
articleFactory.reset();
|
||||
await repo.createArticle(articleFactory.build({ id: "1", title: "A", slug: "a", status: "draft" }));
|
||||
await repo.createArticle(articleFactory.build({ id: "2", title: "B", slug: "b", status: "published" }));
|
||||
await repo.createArticle(
|
||||
articleFactory.build({ id: "1", title: "A", slug: "a", status: "draft" }),
|
||||
);
|
||||
await repo.createArticle(
|
||||
articleFactory.build({
|
||||
id: "2",
|
||||
title: "B",
|
||||
slug: "b",
|
||||
status: "published",
|
||||
}),
|
||||
);
|
||||
|
||||
const useCase = getArticlesUseCase(repo);
|
||||
const result = await useCase({ status: "published" });
|
||||
@@ -29,7 +43,7 @@ describe("getArticlesUseCase", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("getArticlesUseCase output validation (R25)", () => {
|
||||
describe("getArticlesUseCase output validation", () => {
|
||||
it("throws when the repository returns a malformed article", async () => {
|
||||
const repo = new MockArticlesRepository();
|
||||
// bypass the mock's createArticle (which is typed) by reaching into _articles directly
|
||||
|
||||
@@ -40,8 +40,12 @@ export async function bindDevSeedBlog(ctx: BindContext): Promise<void> {
|
||||
if (blogContainer.isBound(INSTRUMENTATION_SYMBOLS.LOGGER)) {
|
||||
blogContainer.unbind(INSTRUMENTATION_SYMBOLS.LOGGER);
|
||||
}
|
||||
blogContainer.bind<ITracer>(INSTRUMENTATION_SYMBOLS.TRACER).toConstantValue(tracer);
|
||||
blogContainer.bind<ILogger>(INSTRUMENTATION_SYMBOLS.LOGGER).toConstantValue(logger);
|
||||
blogContainer
|
||||
.bind<ITracer>(INSTRUMENTATION_SYMBOLS.TRACER)
|
||||
.toConstantValue(tracer);
|
||||
blogContainer
|
||||
.bind<ILogger>(INSTRUMENTATION_SYMBOLS.LOGGER)
|
||||
.toConstantValue(logger);
|
||||
|
||||
if (blogContainer.isBound(BLOG_SYMBOLS.IArticlesRepository)) {
|
||||
blogContainer.unbind(BLOG_SYMBOLS.IArticlesRepository);
|
||||
@@ -93,11 +97,15 @@ export async function bindDevSeedBlog(ctx: BindContext): Promise<void> {
|
||||
]) {
|
||||
if (blogContainer.isBound(sym)) blogContainer.unbind(sym);
|
||||
}
|
||||
blogContainer.bind(BLOG_SYMBOLS.IGetArticlesUseCase).toConstantValue(wrappedGetArticles);
|
||||
blogContainer
|
||||
.bind(BLOG_SYMBOLS.IGetArticlesUseCase)
|
||||
.toConstantValue(wrappedGetArticles);
|
||||
blogContainer
|
||||
.bind(BLOG_SYMBOLS.IGetArticleBySlugUseCase)
|
||||
.toConstantValue(wrappedGetArticleBySlug);
|
||||
blogContainer.bind(BLOG_SYMBOLS.ICreateArticleUseCase).toConstantValue(wrappedCreateArticle);
|
||||
blogContainer
|
||||
.bind(BLOG_SYMBOLS.ICreateArticleUseCase)
|
||||
.toConstantValue(wrappedCreateArticle);
|
||||
|
||||
blogContainer
|
||||
.bind(BLOG_SYMBOLS.IGetArticlesController)
|
||||
@@ -120,7 +128,11 @@ export async function bindDevSeedBlog(ctx: BindContext): Promise<void> {
|
||||
{ name: "blog.getArticleBySlug", op: "controller" },
|
||||
withCapture(
|
||||
logger,
|
||||
{ feature: "blog", layer: "controller", name: "blog.getArticleBySlug" },
|
||||
{
|
||||
feature: "blog",
|
||||
layer: "controller",
|
||||
name: "blog.getArticleBySlug",
|
||||
},
|
||||
getArticleBySlugController(wrappedGetArticleBySlug),
|
||||
),
|
||||
),
|
||||
@@ -138,8 +150,7 @@ export async function bindDevSeedBlog(ctx: BindContext): Promise<void> {
|
||||
),
|
||||
),
|
||||
);
|
||||
// bus + queue are accept-and-forward in Phase 6; consumed by Phase 7 generator
|
||||
// output at the <gen:event-handlers> / <gen:jobs> anchors below.
|
||||
// bus + queue are passed through; generated handlers consume them at the anchors below.
|
||||
void bus;
|
||||
void queue;
|
||||
void realtime;
|
||||
|
||||
@@ -19,7 +19,8 @@ import { getArticleBySlugController } from "../interface-adapters/controllers/ge
|
||||
import { createArticleController } from "../interface-adapters/controllers/create-article.controller";
|
||||
|
||||
export function bindProductionBlog(ctx: BindProductionContext): void {
|
||||
const { config, tracer, logger, bus, queue, realtime, realtimeRegistry } = ctx;
|
||||
const { config, tracer, logger, bus, queue, realtime, realtimeRegistry } =
|
||||
ctx;
|
||||
|
||||
// Bind shared instrumentation into feature container
|
||||
if (blogContainer.isBound(INSTRUMENTATION_SYMBOLS.TRACER)) {
|
||||
@@ -28,8 +29,12 @@ export function bindProductionBlog(ctx: BindProductionContext): void {
|
||||
if (blogContainer.isBound(INSTRUMENTATION_SYMBOLS.LOGGER)) {
|
||||
blogContainer.unbind(INSTRUMENTATION_SYMBOLS.LOGGER);
|
||||
}
|
||||
blogContainer.bind<ITracer>(INSTRUMENTATION_SYMBOLS.TRACER).toConstantValue(tracer);
|
||||
blogContainer.bind<ILogger>(INSTRUMENTATION_SYMBOLS.LOGGER).toConstantValue(logger);
|
||||
blogContainer
|
||||
.bind<ITracer>(INSTRUMENTATION_SYMBOLS.TRACER)
|
||||
.toConstantValue(tracer);
|
||||
blogContainer
|
||||
.bind<ILogger>(INSTRUMENTATION_SYMBOLS.LOGGER)
|
||||
.toConstantValue(logger);
|
||||
|
||||
// Real repository
|
||||
if (blogContainer.isBound(BLOG_SYMBOLS.IArticlesRepository)) {
|
||||
@@ -38,7 +43,7 @@ export function bindProductionBlog(ctx: BindProductionContext): void {
|
||||
const repo = new ArticlesRepository(config, tracer, logger);
|
||||
blogContainer.bind(BLOG_SYMBOLS.IArticlesRepository).toConstantValue(repo);
|
||||
|
||||
// Use cases — wrapped with span + capture at bind time (R41, R44)
|
||||
// Use cases — wrapped with span + capture at bind time
|
||||
const wrappedGetArticles = withSpan(
|
||||
tracer,
|
||||
{ name: "blog.getArticles", op: "use-case" },
|
||||
@@ -76,11 +81,15 @@ export function bindProductionBlog(ctx: BindProductionContext): void {
|
||||
if (blogContainer.isBound(BLOG_SYMBOLS.ICreateArticleUseCase)) {
|
||||
blogContainer.unbind(BLOG_SYMBOLS.ICreateArticleUseCase);
|
||||
}
|
||||
blogContainer.bind(BLOG_SYMBOLS.IGetArticlesUseCase).toConstantValue(wrappedGetArticles);
|
||||
blogContainer
|
||||
.bind(BLOG_SYMBOLS.IGetArticlesUseCase)
|
||||
.toConstantValue(wrappedGetArticles);
|
||||
blogContainer
|
||||
.bind(BLOG_SYMBOLS.IGetArticleBySlugUseCase)
|
||||
.toConstantValue(wrappedGetArticleBySlug);
|
||||
blogContainer.bind(BLOG_SYMBOLS.ICreateArticleUseCase).toConstantValue(wrappedCreateArticle);
|
||||
blogContainer
|
||||
.bind(BLOG_SYMBOLS.ICreateArticleUseCase)
|
||||
.toConstantValue(wrappedCreateArticle);
|
||||
|
||||
// Controllers — wrapped with span at bind time
|
||||
if (blogContainer.isBound(BLOG_SYMBOLS.IGetArticlesController)) {
|
||||
@@ -113,7 +122,11 @@ export function bindProductionBlog(ctx: BindProductionContext): void {
|
||||
{ name: "blog.getArticleBySlug", op: "controller" },
|
||||
withCapture(
|
||||
logger,
|
||||
{ feature: "blog", layer: "controller", name: "blog.getArticleBySlug" },
|
||||
{
|
||||
feature: "blog",
|
||||
layer: "controller",
|
||||
name: "blog.getArticleBySlug",
|
||||
},
|
||||
getArticleBySlugController(wrappedGetArticleBySlug),
|
||||
),
|
||||
),
|
||||
@@ -131,8 +144,7 @@ export function bindProductionBlog(ctx: BindProductionContext): void {
|
||||
),
|
||||
),
|
||||
);
|
||||
// bus + queue are accept-and-forward in Phase 6; consumed by Phase 7 generator
|
||||
// output at the <gen:event-handlers> / <gen:jobs> anchors below.
|
||||
// bus + queue are passed through; generated handlers consume them at the anchors below.
|
||||
void bus;
|
||||
void queue;
|
||||
void realtime;
|
||||
|
||||
@@ -3,7 +3,7 @@ export type { BlogRouter } from "./integrations/api/router";
|
||||
export { ArticleNotFoundError } from "./entities/errors/article";
|
||||
export { InputParseError } from "./entities/errors/common";
|
||||
|
||||
// Use case schemas + types (Plan 9 R18)
|
||||
// Use case schemas + types
|
||||
export {
|
||||
getArticlesInputSchema,
|
||||
getArticlesOutputSchema,
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { RecordingTracer, RecordingLogger } from "@repo/core-testing/instrumentation";
|
||||
import {
|
||||
RecordingTracer,
|
||||
RecordingLogger,
|
||||
} from "@repo/core-testing/instrumentation";
|
||||
import { MockArticlesRepository } from "@/infrastructure/repositories/articles.repository.mock";
|
||||
|
||||
// Mock repo also wraps in spans (R42); easier to assert without booting Payload.
|
||||
describe("MockArticlesRepository emits spans (R42)", () => {
|
||||
// Mock repo also wraps in spans; easier to assert without booting Payload.
|
||||
describe("MockArticlesRepository emits spans", () => {
|
||||
it("getArticles emits one span with op='repository'", async () => {
|
||||
const tracer = new RecordingTracer();
|
||||
const logger = new RecordingLogger();
|
||||
@@ -31,7 +34,9 @@ describe("MockArticlesRepository emits spans (R42)", () => {
|
||||
updatedAt: new Date(),
|
||||
});
|
||||
expect(tracer.findSpan("articles.createArticle")).toBeDefined();
|
||||
expect(tracer.findSpan("articles.createArticle")!.attributes.slug).toBe("t");
|
||||
expect(tracer.findSpan("articles.createArticle")!.attributes.slug).toBe(
|
||||
"t",
|
||||
);
|
||||
});
|
||||
|
||||
it("getArticle records found=false for missing id", async () => {
|
||||
|
||||
@@ -45,7 +45,7 @@ describe("blogRouter", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("blogRouter (R26 error mapping)", () => {
|
||||
describe("blogRouter error mapping", () => {
|
||||
beforeEach(() => {
|
||||
blogContainer.unbindAll();
|
||||
blogContainer.load(BlogModule);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// React Query option builders for blog feature procedures.
|
||||
// Consumed by apps via the @repo/core-trpc client (wired in Plan 5).
|
||||
// Consumed by apps via the @repo/core-trpc client.
|
||||
|
||||
type TrpcClient = {
|
||||
blog: {
|
||||
@@ -23,7 +23,12 @@ export function articleBySlugQuery(client: TrpcClient, slug: string) {
|
||||
|
||||
export function listArticlesQuery(
|
||||
client: TrpcClient,
|
||||
options?: { status?: string; authorId?: string; limit?: number; offset?: number },
|
||||
options?: {
|
||||
status?: string;
|
||||
authorId?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
},
|
||||
) {
|
||||
return client.blog.listArticles.queryOptions(options);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user