refactor(blog): migrate binders to wireUseCase for all 3 use cases

Replace inline withSpan + withCapture blocks for getArticles,
getArticleBySlug, and createArticle in both bind-production and
bind-dev-seed with wireUseCase calls.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-13 17:55:43 +00:00
parent 7406171b0b
commit 43d88be4bd
2 changed files with 98 additions and 115 deletions

View File

@@ -6,7 +6,10 @@ import {
type ILogger,
} from "@repo/core-shared/instrumentation";
import type { BindContext } from "@repo/core-shared/di";
import { assertFeatureConformance } from "@repo/core-shared/conformance";
import {
assertFeatureConformance,
wireUseCase,
} from "@repo/core-shared/conformance";
import { blogManifest } from "../feature.manifest.js";
import { blogContainer } from "./container.js";
import { BLOG_SYMBOLS } from "./symbols.js";
@@ -58,54 +61,48 @@ export async function bindDevSeedBlog(ctx: BindContext): Promise<void> {
.bind<IArticlesRepository>(BLOG_SYMBOLS.IArticlesRepository)
.toConstantValue(repo);
// Wrap use cases + controllers identically to bind-production
const wrappedGetArticles = withSpan(
// Use cases
const wrappedGetArticles = wireUseCase({
container: blogContainer,
symbol: BLOG_SYMBOLS.IGetArticlesUseCase,
factory: getArticlesUseCase,
deps: [repo],
feature: "blog",
layer: "use-case",
name: "getArticles",
tracer,
{ name: "blog.getArticles", op: "use-case" },
withCapture(
logger,
{ feature: "blog", layer: "use-case", name: "blog.getArticles" },
getArticlesUseCase(repo),
),
);
const wrappedGetArticleBySlug = withSpan(
logger,
});
const wrappedGetArticleBySlug = wireUseCase({
container: blogContainer,
symbol: BLOG_SYMBOLS.IGetArticleBySlugUseCase,
factory: getArticleBySlugUseCase,
deps: [repo],
feature: "blog",
layer: "use-case",
name: "getArticleBySlug",
tracer,
{ name: "blog.getArticleBySlug", op: "use-case" },
withCapture(
logger,
{ feature: "blog", layer: "use-case", name: "blog.getArticleBySlug" },
getArticleBySlugUseCase(repo),
),
);
const wrappedCreateArticle = withSpan(
logger,
});
const wrappedCreateArticle = wireUseCase({
container: blogContainer,
symbol: BLOG_SYMBOLS.ICreateArticleUseCase,
factory: createArticleUseCase,
deps: [repo],
feature: "blog",
layer: "use-case",
name: "createArticle",
tracer,
{ name: "blog.createArticle", op: "use-case" },
withCapture(
logger,
{ feature: "blog", layer: "use-case", name: "blog.createArticle" },
createArticleUseCase(repo),
),
);
logger,
});
for (const sym of [
BLOG_SYMBOLS.IGetArticlesUseCase,
BLOG_SYMBOLS.IGetArticleBySlugUseCase,
BLOG_SYMBOLS.ICreateArticleUseCase,
BLOG_SYMBOLS.IGetArticlesController,
BLOG_SYMBOLS.IGetArticleBySlugController,
BLOG_SYMBOLS.ICreateArticleController,
]) {
if (blogContainer.isBound(sym)) blogContainer.unbind(sym);
}
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.IGetArticlesController)
@@ -120,23 +117,21 @@ export async function bindDevSeedBlog(ctx: BindContext): Promise<void> {
),
),
);
blogContainer
.bind(BLOG_SYMBOLS.IGetArticleBySlugController)
.toConstantValue(
withSpan(
tracer,
{ name: "blog.getArticleBySlug", op: "controller" },
withCapture(
logger,
{
feature: "blog",
layer: "controller",
name: "blog.getArticleBySlug",
},
getArticleBySlugController(wrappedGetArticleBySlug),
),
blogContainer.bind(BLOG_SYMBOLS.IGetArticleBySlugController).toConstantValue(
withSpan(
tracer,
{ name: "blog.getArticleBySlug", op: "controller" },
withCapture(
logger,
{
feature: "blog",
layer: "controller",
name: "blog.getArticleBySlug",
},
getArticleBySlugController(wrappedGetArticleBySlug),
),
);
),
);
blogContainer
.bind(BLOG_SYMBOLS.ICreateArticleController)
.toConstantValue(

View File

@@ -6,7 +6,10 @@ import {
type ILogger,
} from "@repo/core-shared/instrumentation";
import type { BindProductionContext } from "@repo/core-shared/di";
import { assertFeatureConformance } from "@repo/core-shared/conformance";
import {
assertFeatureConformance,
wireUseCase,
} from "@repo/core-shared/conformance";
import { blogContainer } from "./container";
import { BLOG_SYMBOLS } from "./symbols";
import { blogManifest } from "../feature.manifest";
@@ -43,53 +46,40 @@ 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
const wrappedGetArticles = withSpan(
// Use cases
const wrappedGetArticles = wireUseCase({
container: blogContainer,
symbol: BLOG_SYMBOLS.IGetArticlesUseCase,
factory: getArticlesUseCase,
deps: [repo],
feature: "blog",
layer: "use-case",
name: "getArticles",
tracer,
{ name: "blog.getArticles", op: "use-case" },
withCapture(
logger,
{ feature: "blog", layer: "use-case", name: "blog.getArticles" },
getArticlesUseCase(repo),
),
);
const wrappedGetArticleBySlug = withSpan(
logger,
});
const wrappedGetArticleBySlug = wireUseCase({
container: blogContainer,
symbol: BLOG_SYMBOLS.IGetArticleBySlugUseCase,
factory: getArticleBySlugUseCase,
deps: [repo],
feature: "blog",
layer: "use-case",
name: "getArticleBySlug",
tracer,
{ name: "blog.getArticleBySlug", op: "use-case" },
withCapture(
logger,
{ feature: "blog", layer: "use-case", name: "blog.getArticleBySlug" },
getArticleBySlugUseCase(repo),
),
);
const wrappedCreateArticle = withSpan(
logger,
});
const wrappedCreateArticle = wireUseCase({
container: blogContainer,
symbol: BLOG_SYMBOLS.ICreateArticleUseCase,
factory: createArticleUseCase,
deps: [repo],
feature: "blog",
layer: "use-case",
name: "createArticle",
tracer,
{ name: "blog.createArticle", op: "use-case" },
withCapture(
logger,
{ feature: "blog", layer: "use-case", name: "blog.createArticle" },
createArticleUseCase(repo),
),
);
if (blogContainer.isBound(BLOG_SYMBOLS.IGetArticlesUseCase)) {
blogContainer.unbind(BLOG_SYMBOLS.IGetArticlesUseCase);
}
if (blogContainer.isBound(BLOG_SYMBOLS.IGetArticleBySlugUseCase)) {
blogContainer.unbind(BLOG_SYMBOLS.IGetArticleBySlugUseCase);
}
if (blogContainer.isBound(BLOG_SYMBOLS.ICreateArticleUseCase)) {
blogContainer.unbind(BLOG_SYMBOLS.ICreateArticleUseCase);
}
blogContainer
.bind(BLOG_SYMBOLS.IGetArticlesUseCase)
.toConstantValue(wrappedGetArticles);
blogContainer
.bind(BLOG_SYMBOLS.IGetArticleBySlugUseCase)
.toConstantValue(wrappedGetArticleBySlug);
blogContainer
.bind(BLOG_SYMBOLS.ICreateArticleUseCase)
.toConstantValue(wrappedCreateArticle);
logger,
});
// Controllers — wrapped with span at bind time
if (blogContainer.isBound(BLOG_SYMBOLS.IGetArticlesController)) {
@@ -114,23 +104,21 @@ export function bindProductionBlog(ctx: BindProductionContext): void {
),
),
);
blogContainer
.bind(BLOG_SYMBOLS.IGetArticleBySlugController)
.toConstantValue(
withSpan(
tracer,
{ name: "blog.getArticleBySlug", op: "controller" },
withCapture(
logger,
{
feature: "blog",
layer: "controller",
name: "blog.getArticleBySlug",
},
getArticleBySlugController(wrappedGetArticleBySlug),
),
blogContainer.bind(BLOG_SYMBOLS.IGetArticleBySlugController).toConstantValue(
withSpan(
tracer,
{ name: "blog.getArticleBySlug", op: "controller" },
withCapture(
logger,
{
feature: "blog",
layer: "controller",
name: "blog.getArticleBySlug",
},
getArticleBySlugController(wrappedGetArticleBySlug),
),
);
),
);
blogContainer
.bind(BLOG_SYMBOLS.ICreateArticleController)
.toConstantValue(