docs: events now optional — Status headers + conditional HTML rendering

- ADR-015: Status → Optional with scaffold command + behavior note (bus absent
  means no-op, IJobQueue unaffected)
- events-and-jobs.md: prerequisite callout block explaining core-events is
  optional, how to scaffold, and which features require it
- data-flow-explainer.html: note bus is optional in BindProductionContext blurb;
  add inline comment in code snippet that bus is scaffoldable

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-09 14:01:38 +02:00
parent a9f27f0d7e
commit 3d653666c2
3 changed files with 20 additions and 2 deletions

View File

@@ -1703,6 +1703,7 @@ footer .colophon {
<h3>blog/di/<em>bind-production.ts</em></h3>
<p>Called from each app's bootstrap (<code>apps/web-next/src/server/bind-production.ts</code>) with the <code>ctx</code> object built once by the aggregator. <code>BindProductionContext</code> is imported from <code>@repo/core-shared/di</code>.</p>
<pre class="code" data-lang="typescript // packages/blog/src/di/bind-production.ts"><span class="k">export function</span> <span class="n">bindProductionBlog</span>(<span class="n">ctx</span>: <span class="t">BindProductionContext</span>): <span class="t">void</span> {
<span class="c">// bus is optional — present only when @repo/core-events is scaffolded</span>
<span class="k">const</span> { <span class="n">config</span>, <span class="n">tracer</span>, <span class="n">logger</span>, <span class="n">bus</span>, <span class="n">queue</span>, <span class="n">realtime</span>, <span class="n">realtimeRegistry</span> } = <span class="n">ctx</span>;
<span class="k">if</span> (<span class="n">blogContainer</span>.<span class="n">isBound</span>(<span class="n">BLOG_SYMBOLS</span>.<span class="n">IArticlesRepository</span>)) {
<span class="n">blogContainer</span>.<span class="n">unbind</span>(<span class="n">BLOG_SYMBOLS</span>.<span class="n">IArticlesRepository</span>);
@@ -2192,7 +2193,7 @@ footer .colophon {
<div class="tradeoff-card">
<div class="tag">di/bind-production.ts</div>
<h3>Production binder</h3>
<p class="blurb"><code>bindProduction&lt;F&gt;(ctx: BindProductionContext)</code> — unbinds the mock, rebinds the real Payload-backed impl. The <code>ctx</code> arg carries required fields (<code>tracer</code>, <code>logger</code>, <code>config</code>) and optional cross-cutting deps (<code>bus</code>, <code>queue</code>). Realtime deps (<code>realtime</code>, <code>realtimeRegistry</code>) are also optional — present only when <code>@repo/core-realtime</code> is scaffolded via <code>pnpm turbo gen core-package realtime</code>.</p>
<p class="blurb"><code>bindProduction&lt;F&gt;(ctx: BindProductionContext)</code> — unbinds the mock, rebinds the real Payload-backed impl. The <code>ctx</code> arg carries required fields (<code>tracer</code>, <code>logger</code>, <code>config</code>) and optional cross-cutting deps (<code>queue</code>). Event bus (<code>bus</code>) is also optional — present only when <code>@repo/core-events</code> is scaffolded via <code>pnpm turbo gen core-package events</code>; absent, <code>bus?.subscribe/publish</code> calls are no-ops. Realtime deps (<code>realtime</code>, <code>realtimeRegistry</code>) are also optional — present only when <code>@repo/core-realtime</code> is scaffolded via <code>pnpm turbo gen core-package realtime</code>.</p>
<div class="pc-cols">
<div class="pros"><h5>Pros</h5><ul>
<li>Decouples Payload config from the feature package — boundary stays clean</li>

View File

@@ -1,6 +1,11 @@
# ADR-015 — Cross-feature events and background jobs
**Status:** Accepted
**Status:** Optional — scaffold via `pnpm turbo gen core-package events`.
When absent, `ctx.bus` is undefined and feature binders' `bus?.subscribe/publish`
calls are silent no-ops. Cross-feature event fanout does not operate until
core-events is scaffolded. `IJobQueue` (in `@repo/core-shared/jobs`) and the
`gen event`/`gen job` generators remain fully functional without core-events.
**Date:** 2026-05-08
**Spec:** docs/superpowers/specs/2026-05-08-events-and-jobs-design.md
**Plan:** docs/superpowers/plans/2026-05-08-events-and-jobs.md

View File

@@ -2,6 +2,18 @@
Walkthrough for adding cross-feature events and background jobs to a feature. For the architectural rationale, see [ADR-015](../decisions/adr-015-events-and-jobs.md) and [the full spec](../superpowers/specs/2026-05-08-events-and-jobs-design.md).
> **Prerequisite — `@repo/core-events` is optional.**
> The event bus (`IEventBus`, `InMemoryEventBus`, `PayloadJobsEventBus`) lives
> in `@repo/core-events`, which ships as a scaffoldable package rather than a
> permanent fixture. If `packages/core-events/` does not exist in your repo,
> run `pnpm turbo gen core-package events` first, then wire the bus into
> `apps/web-next/src/server/bind-production.ts` as described in the generator's
> next-steps output.
>
> Background jobs (`IJobQueue`, `gen job`) work without core-events — they only
> require `@repo/core-shared/jobs`. Cross-feature event fanout (`gen event
> consume`) additionally requires core-events.
The three rules to keep in mind:
- **E0** — Events are for cross-feature decoupling. In-feature reactions are direct use-case calls.