Files
agentic-dev/packages/navigation/src/di/bind-production.ts

92 lines
3.3 KiB
TypeScript

import {
withSpan,
withCapture,
INSTRUMENTATION_SYMBOLS,
type ITracer,
type ILogger,
} from "@repo/core-shared/instrumentation";
import type { BindProductionContext } from "@repo/core-shared/di";
import { assertFeatureConformance } from "@repo/core-shared/conformance";
import { navigationContainer } from "./container";
import { NAVIGATION_SYMBOLS } from "./symbols";
import { navigationManifest } from "../feature.manifest";
import { HeaderRepository } from "../infrastructure/repositories/header.repository";
import { getHeaderUseCase } from "../application/use-cases/get-header.use-case";
import { getHeaderController } from "../interface-adapters/controllers/get-header.controller";
export function bindProductionNavigation(ctx: BindProductionContext): void {
const { config, tracer, logger, bus, queue, realtime, realtimeRegistry } = ctx;
// Bind shared instrumentation into feature container
if (navigationContainer.isBound(INSTRUMENTATION_SYMBOLS.TRACER)) {
navigationContainer.unbind(INSTRUMENTATION_SYMBOLS.TRACER);
}
if (navigationContainer.isBound(INSTRUMENTATION_SYMBOLS.LOGGER)) {
navigationContainer.unbind(INSTRUMENTATION_SYMBOLS.LOGGER);
}
navigationContainer.bind<ITracer>(INSTRUMENTATION_SYMBOLS.TRACER).toConstantValue(tracer);
navigationContainer.bind<ILogger>(INSTRUMENTATION_SYMBOLS.LOGGER).toConstantValue(logger);
// Real repository
if (navigationContainer.isBound(NAVIGATION_SYMBOLS.IHeaderRepository)) {
navigationContainer.unbind(NAVIGATION_SYMBOLS.IHeaderRepository);
}
const repo = new HeaderRepository(config, tracer, logger);
navigationContainer
.bind(NAVIGATION_SYMBOLS.IHeaderRepository)
.toConstantValue(repo);
// Use case — wrapped with span + capture at bind time
const wrappedGetHeader = withSpan(
tracer,
{ name: "navigation.getHeader", op: "use-case" },
withCapture(
logger,
{ feature: "navigation", layer: "use-case", name: "navigation.getHeader" },
getHeaderUseCase(repo),
),
);
if (navigationContainer.isBound(NAVIGATION_SYMBOLS.IGetHeaderUseCase)) {
navigationContainer.unbind(NAVIGATION_SYMBOLS.IGetHeaderUseCase);
}
navigationContainer
.bind(NAVIGATION_SYMBOLS.IGetHeaderUseCase)
.toConstantValue(wrappedGetHeader);
// Controller — wrapped with span at bind time
if (navigationContainer.isBound(NAVIGATION_SYMBOLS.IGetHeaderController)) {
navigationContainer.unbind(NAVIGATION_SYMBOLS.IGetHeaderController);
}
navigationContainer
.bind(NAVIGATION_SYMBOLS.IGetHeaderController)
.toConstantValue(
withSpan(
tracer,
{ name: "navigation.getHeader", op: "controller" },
withCapture(
logger,
{ feature: "navigation", layer: "controller", name: "navigation.getHeader" },
getHeaderController(wrappedGetHeader),
),
),
);
// bus + queue are accept-and-forward in Phase 6; consumed by Phase 7 generator
// output at the <gen:event-handlers> / <gen:jobs> anchors below.
void bus;
void queue;
void realtime;
void realtimeRegistry;
// <gen:event-handlers>
// <gen:jobs>
// <gen:realtime-handlers>
// Boot-time conformance check.
assertFeatureConformance(
navigationContainer,
navigationManifest,
{ getHeader: NAVIGATION_SYMBOLS.IGetHeaderUseCase },
ctx,
);
}