import { withSpan, withCapture, INSTRUMENTATION_SYMBOLS, type ITracer, type ILogger, } from "@repo/core-shared/instrumentation"; import type { BindContext } from "@repo/core-shared/di"; import { assertFeatureConformance, wireUseCase, } from "@repo/core-shared/conformance"; import { workspacesManifest } from "../feature.manifest"; import { workspacesContainer } from "./container"; import { WORKSPACES_SYMBOLS } from "./symbols"; import { MockWorkspaceRepository } from "../infrastructure/repositories/workspace.repository.mock"; import { buildDevWorkspaceMap } from "../__seeds__/dev"; import { getWorkspaceUseCase } from "../application/use-cases/get-workspace.use-case"; import { getWorkspaceController } from "../interface-adapters/controllers/get-workspace.controller"; import type { IWorkspaceRepository } from "../application/repositories/workspace.repository.interface"; /** * Replace the default mock with a populated one for dev mode + storybook. * * Mutually exclusive with `bindProductionWorkspaces(ctx)`. * Tests must NOT call this — they construct `new MockWorkspaceRepository()` * directly and seed via factories per-test. * * Idempotent: safe to call multiple times; each call rebuilds a fresh * populated repo and rebinds the symbol. */ export async function bindDevSeedWorkspaces(ctx: BindContext): Promise { const { tracer, logger, bus, queue, realtime, realtimeRegistry } = ctx; // Bind shared instrumentation into feature container if (workspacesContainer.isBound(INSTRUMENTATION_SYMBOLS.TRACER)) { workspacesContainer.unbind(INSTRUMENTATION_SYMBOLS.TRACER); } if (workspacesContainer.isBound(INSTRUMENTATION_SYMBOLS.LOGGER)) { workspacesContainer.unbind(INSTRUMENTATION_SYMBOLS.LOGGER); } workspacesContainer .bind(INSTRUMENTATION_SYMBOLS.TRACER) .toConstantValue(tracer); workspacesContainer .bind(INSTRUMENTATION_SYMBOLS.LOGGER) .toConstantValue(logger); if (workspacesContainer.isBound(WORKSPACES_SYMBOLS.IWorkspaceRepository)) { workspacesContainer.unbind(WORKSPACES_SYMBOLS.IWorkspaceRepository); } const repo = new MockWorkspaceRepository( buildDevWorkspaceMap(), tracer, logger, ); workspacesContainer .bind(WORKSPACES_SYMBOLS.IWorkspaceRepository) .toConstantValue(repo); // Use case const wrappedGetWorkspace = wireUseCase({ container: workspacesContainer, symbol: WORKSPACES_SYMBOLS.IGetWorkspaceUseCase, factory: getWorkspaceUseCase, deps: [repo], feature: "workspaces", layer: "use-case", name: "getWorkspace", tracer, logger, }); if (workspacesContainer.isBound(WORKSPACES_SYMBOLS.IGetWorkspaceController)) { workspacesContainer.unbind(WORKSPACES_SYMBOLS.IGetWorkspaceController); } workspacesContainer .bind(WORKSPACES_SYMBOLS.IGetWorkspaceController) .toConstantValue( withSpan( tracer, { name: "workspaces.getWorkspace", op: "controller" }, withCapture( logger, { feature: "workspaces", layer: "controller", name: "workspaces.getWorkspace", }, getWorkspaceController(wrappedGetWorkspace), ), ), ); // 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 (dev-seed mode). assertFeatureConformance( workspacesContainer, workspacesManifest, { getWorkspace: WORKSPACES_SYMBOLS.IGetWorkspaceUseCase, }, ctx, ); }