Webpack (Next.js transpilePackages) resolves from .ts source directly and cannot find .js files. The bind-production binders already used extensionless imports; align bind-dev-seed to match. Also fixes the turbo gen feature template so new features are consistent.
108 lines
3.6 KiB
TypeScript
108 lines
3.6 KiB
TypeScript
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 { navigationManifest } from "../feature.manifest";
|
|
import { navigationContainer } from "./container";
|
|
import { NAVIGATION_SYMBOLS } from "./symbols";
|
|
import { MockHeaderRepository } from "../infrastructure/repositories/header.repository.mock";
|
|
import { buildDevHeader } from "../__seeds__/dev";
|
|
import { getHeaderUseCase } from "../application/use-cases/get-header.use-case";
|
|
import { getHeaderController } from "../interface-adapters/controllers/get-header.controller";
|
|
import type { IHeaderRepository } from "../application/repositories/header.repository.interface";
|
|
|
|
/**
|
|
* Replace the default mock with a populated one for dev mode + storybook.
|
|
*
|
|
* Call this from app boot when `USE_DEV_SEED=true`, mutually exclusive with
|
|
* `bindProductionNavigation(config)`. Tests must NOT call this — they
|
|
* construct `new MockHeaderRepository()` 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 bindDevSeedNavigation(ctx: BindContext): Promise<void> {
|
|
const { 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);
|
|
|
|
if (navigationContainer.isBound(NAVIGATION_SYMBOLS.IHeaderRepository)) {
|
|
navigationContainer.unbind(NAVIGATION_SYMBOLS.IHeaderRepository);
|
|
}
|
|
const repo = new MockHeaderRepository(buildDevHeader(), tracer, logger);
|
|
navigationContainer
|
|
.bind<IHeaderRepository>(NAVIGATION_SYMBOLS.IHeaderRepository)
|
|
.toConstantValue(repo);
|
|
|
|
// Use case
|
|
const wrappedGetHeader = wireUseCase({
|
|
container: navigationContainer,
|
|
symbol: NAVIGATION_SYMBOLS.IGetHeaderUseCase,
|
|
factory: getHeaderUseCase,
|
|
deps: [repo],
|
|
feature: "navigation",
|
|
layer: "use-case",
|
|
name: "getHeader",
|
|
tracer,
|
|
logger,
|
|
});
|
|
|
|
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 passed through; generated handlers consume them at the anchors below.
|
|
void bus;
|
|
void queue;
|
|
void realtime;
|
|
void realtimeRegistry;
|
|
// <gen:event-handlers>
|
|
// <gen:jobs>
|
|
// <gen:realtime-handlers>
|
|
|
|
// Boot-time conformance check (dev-seed mode).
|
|
assertFeatureConformance(
|
|
navigationContainer,
|
|
navigationManifest,
|
|
{ getHeader: NAVIGATION_SYMBOLS.IGetHeaderUseCase },
|
|
ctx,
|
|
);
|
|
}
|