docs: refresh explainers + adding-a-feature with full binder signature

di-explainer and data-flow-explainer narratives still showed the
pre-ADR-014 1-arg bindProductionBlog(config) form. Updated both
explainers to (config, tracer, logger, bus, queue), and adjusted the
narrative arc so the production-swap step mentions the
resolveEventsAndJobs* preamble.

adding-a-feature's Step 16 sketch was the same 1-arg shape; replaced
with the canonical 5-arg signature and a short note that the bus/queue
params are accept-and-forward until gen event consume / gen job
generators inject usage at the anchors. Pointer to a real feature's
bind-production.ts for the complete reference.

Final sweep is clean — no stale (container, config) or 1-arg
bindProduction signatures remain in docs/.
This commit is contained in:
2026-05-08 17:54:11 +02:00
parent 5a2234f7ad
commit 69c445de26
3 changed files with 32 additions and 8 deletions

View File

@@ -756,7 +756,7 @@ footer .colophon {
<div class="cast-tag">file 04 · prod swap</div>
<h3>bind-production.ts</h3>
<p class="role">Replaces the mock repository binding with a real Payload-backed one at app boot.</p>
<p>Exports <code>bindProductionBlog(config: SanitizedConfig)</code>. Function body: <code>blogContainer.unbind(symbol)</code> if already bound, then <code>.bind(symbol).toConstantValue(new ArticlesRepository(config))</code>. Use cases and controllers stay bound to their factory bindings — they will fetch the new repo through the container automatically because their factories call <code>ctx.container.get(...)</code> at every resolution.</p>
<p>Exports <code>bindProductionBlog(config, tracer, logger, bus, queue)</code>. Function body: <code>blogContainer.unbind(symbol)</code> if already bound, then <code>.bind(symbol).toConstantValue(new ArticlesRepository(config, tracer, logger))</code>. Use cases and controllers are wrapped via <code>withSpan(withCapture(factory(deps)))</code> at bind time so they inherit instrumentation without changing their factory bodies. The <code>bus</code> and <code>queue</code> params come from the app's <code>resolveEventsAndJobs*</code> step (ADR-015) and feed the <code>// &lt;gen:event-handlers&gt;</code> / <code>// &lt;gen:jobs&gt;</code> injection sites.</p>
<div class="runs-when"><strong>When it runs:</strong> called from app boot (<code>apps/web-next/src/server/bind-production.ts</code>) when <code>USE_DEV_SEED ≠ "true"</code> AND Payload config is resolvable.</div>
</div>
@@ -1302,8 +1302,8 @@ const MODES = {
scenarioTag: 'when this happens',
title: 'Production binder ran at app boot',
narrative: [
"App's bindAll() did not see USE_DEV_SEED=true, so it dispatched to bindAllProduction(config). That awaited the resolved Payload config and called bindProductionBlog(config).",
"The binder unbound IArticlesRepository and rebound it with .toConstantValue(new ArticlesRepository(config)) — the real Payload-backed implementation that will hit Postgres on every method call.",
"App's bindAll() did not see USE_DEV_SEED=true, so it dispatched to bindAllProduction(). That resolved instrumentation (Rule 0), resolved a Payload-backed bus + queue (ADR-015), awaited the Payload config, and called bindProductionBlog(config, tracer, logger, bus, queue).",
"The binder unbound IArticlesRepository and rebound it with .toConstantValue(new ArticlesRepository(config, tracer, logger)) — the real Payload-backed implementation that will hit Postgres on every method call.",
"Use cases and controllers still resolve through their .toDynamicValue closures, but the closures now fetch the real repo. Callers cannot tell the difference — same interface, different storage."
],
bindings: [