feat(core-shared): add wireUseCase helper to conformance barrel

Encapsulates withSpan(withCapture(withAudit?(factory(deps)))) composition
and container binding into a single helper, eliminating the structural
boilerplate clone groups repeated across every feature binder pair.

Callers pass { container, symbol, factory, deps, feature, layer, name,
tracer, logger, auditLog? } and get back a fully brand-stacked, container-
bound wired value. Idempotent: unbinds an existing symbol before rebinding.

withAudit lives in core-audit which core-shared cannot import (dependency
inversion: core-audit depends on core-shared). The audit path here replicates
the same semantics — forwarding wrapper + __audited brand — without the
circular dependency.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-13 17:28:57 +00:00
parent 317ec518aa
commit 1bbe866a5c
3 changed files with 362 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
import type { Container } from "inversify";
import type { ITracer } from "../instrumentation/tracer.interface";
import type { ILogger } from "../instrumentation/logger.interface";
import type { AuditLogProtocol } from "../di/bind-protocols";
import { withSpan } from "../instrumentation/with-span";
import { withCapture } from "../instrumentation/with-capture";
import { attachBrand } from "./brand-runtime";
export type WireUseCaseOptions<
Deps extends unknown[],
FnArgs extends unknown[],
R,
> = {
container: Container;
symbol: symbol;
factory: (...deps: Deps) => (...args: FnArgs) => Promise<R>;
deps: Deps;
feature: string;
layer: string;
name: string;
tracer: ITracer;
logger: ILogger;
auditLog?: AuditLogProtocol;
};
/**
* Encapsulates the withSpan(withCapture(withAudit?(factory(deps)))) composition
* and performs the container bind step. Callers pass options and get back a
* brand-stacked wired value that is also bound to the container symbol.
*
* Idempotent: if the symbol is already bound, the old binding is replaced.
*
* withAudit lives in @repo/core-audit which core-shared cannot import (dependency
* inversion: core-audit depends on core-shared, not vice versa). The audit branch
* here replicates the same semantics — forwarding wrapper + __audited brand —
* without introducing the circular dependency.
*/
export function wireUseCase<
Deps extends unknown[],
FnArgs extends unknown[],
R,
>(opts: WireUseCaseOptions<Deps, FnArgs, R>): (...args: FnArgs) => Promise<R> {
const {
container,
symbol,
factory,
deps,
feature,
layer,
name,
tracer,
logger,
auditLog,
} = opts;
const spanName = `${feature}.${name}`;
const captureTags = { feature, layer, name: spanName };
const raw = factory(...deps);
let toWrap: (...args: FnArgs) => Promise<R>;
if (auditLog !== undefined) {
void auditLog; // reserved for future automated audit recording from manifest declarations
const audited: (...args: FnArgs) => Promise<R> = (...args) => raw(...args);
attachBrand(audited, "__audited");
toWrap = audited;
} else {
toWrap = raw;
}
const wired = withSpan(
tracer,
{ name: spanName, op: layer },
withCapture(logger, captureTags, toWrap),
);
if (container.isBound(symbol)) {
container.unbind(symbol);
}
container.bind(symbol).toConstantValue(wired);
return wired;
}