import { withSpan, withCapture, INSTRUMENTATION_SYMBOLS, type ITracer, type ILogger, } from "@repo/core-shared/instrumentation"; import type { BindProductionContext } from "@repo/core-shared/di"; import { assertFeatureConformance, wireUseCase, } from "@repo/core-shared/conformance"; import { mediaContainer } from "./container"; import { MEDIA_SYMBOLS } from "./symbols"; import { mediaManifest } from "../feature.manifest"; import { MediaRepository } from "../infrastructure/repositories/media.repository"; import { getMediaUseCase } from "../application/use-cases/get-media.use-case"; import { listMediaUseCase } from "../application/use-cases/list-media.use-case"; import { deleteMediaUseCase } from "../application/use-cases/delete-media.use-case"; import { getMediaController } from "../interface-adapters/controllers/get-media.controller"; import { listMediaController } from "../interface-adapters/controllers/list-media.controller"; import { deleteMediaController } from "../interface-adapters/controllers/delete-media.controller"; export function bindProductionMedia(ctx: BindProductionContext): void { const { config, tracer, logger, bus, queue, realtime, realtimeRegistry } = ctx; // Bind shared instrumentation into feature container if (mediaContainer.isBound(INSTRUMENTATION_SYMBOLS.TRACER)) { mediaContainer.unbind(INSTRUMENTATION_SYMBOLS.TRACER); } if (mediaContainer.isBound(INSTRUMENTATION_SYMBOLS.LOGGER)) { mediaContainer.unbind(INSTRUMENTATION_SYMBOLS.LOGGER); } mediaContainer .bind(INSTRUMENTATION_SYMBOLS.TRACER) .toConstantValue(tracer); mediaContainer .bind(INSTRUMENTATION_SYMBOLS.LOGGER) .toConstantValue(logger); // Real repository if (mediaContainer.isBound(MEDIA_SYMBOLS.IMediaRepository)) { mediaContainer.unbind(MEDIA_SYMBOLS.IMediaRepository); } const repo = new MediaRepository(config, tracer, logger); mediaContainer.bind(MEDIA_SYMBOLS.IMediaRepository).toConstantValue(repo); // Use cases const wrappedGetMedia = wireUseCase({ container: mediaContainer, symbol: MEDIA_SYMBOLS.IGetMediaUseCase, factory: getMediaUseCase, deps: [repo], feature: "media", layer: "use-case", name: "getMedia", tracer, logger, }); const wrappedListMedia = wireUseCase({ container: mediaContainer, symbol: MEDIA_SYMBOLS.IListMediaUseCase, factory: listMediaUseCase, deps: [repo], feature: "media", layer: "use-case", name: "listMedia", tracer, logger, }); const wrappedDeleteMedia = wireUseCase({ container: mediaContainer, symbol: MEDIA_SYMBOLS.IDeleteMediaUseCase, factory: deleteMediaUseCase, deps: [repo], feature: "media", layer: "use-case", name: "deleteMedia", tracer, logger, }); // Controllers — wrapped with span at bind time for (const sym of [ MEDIA_SYMBOLS.IGetMediaController, MEDIA_SYMBOLS.IListMediaController, MEDIA_SYMBOLS.IDeleteMediaController, ]) { if (mediaContainer.isBound(sym)) mediaContainer.unbind(sym); } mediaContainer .bind(MEDIA_SYMBOLS.IGetMediaController) .toConstantValue( withSpan( tracer, { name: "media.getMedia", op: "controller" }, withCapture( logger, { feature: "media", layer: "controller", name: "media.getMedia" }, getMediaController(wrappedGetMedia), ), ), ); mediaContainer .bind(MEDIA_SYMBOLS.IListMediaController) .toConstantValue( withSpan( tracer, { name: "media.listMedia", op: "controller" }, withCapture( logger, { feature: "media", layer: "controller", name: "media.listMedia" }, listMediaController(wrappedListMedia), ), ), ); mediaContainer .bind(MEDIA_SYMBOLS.IDeleteMediaController) .toConstantValue( withSpan( tracer, { name: "media.deleteMedia", op: "controller" }, withCapture( logger, { feature: "media", layer: "controller", name: "media.deleteMedia" }, deleteMediaController(wrappedDeleteMedia), ), ), ); // bus + queue are passed through; generated handlers consume them at the anchors below. void bus; void queue; void realtime; void realtimeRegistry; // // // // Boot-time conformance check. assertFeatureConformance( mediaContainer, mediaManifest, { getMedia: MEDIA_SYMBOLS.IGetMediaUseCase, listMedia: MEDIA_SYMBOLS.IListMediaUseCase, deleteMedia: MEDIA_SYMBOLS.IDeleteMediaUseCase, }, ctx, ); }