diff --git a/docs/architecture/data-flow-explainer.html b/docs/architecture/data-flow-explainer.html index faca525..7b9691d 100644 --- a/docs/architecture/data-flow-explainer.html +++ b/docs/architecture/data-flow-explainer.html @@ -1664,7 +1664,7 @@ footer .colophon {
The BlogModule binds IArticlesRepository to MockArticlesRepository by default — useful at dev/test time. At app boot, bindProductionBlog(config) unbinds the symbol and rebinds it to new ArticlesRepository(config). Use cases and controllers don't notice — they get whatever the symbol currently resolves to.
The BlogModule binds IArticlesRepository to MockArticlesRepository by default — useful at dev/test time. At app boot, bindProductionBlog(config, tracer, logger, bus, queue) unbinds the symbol and rebinds it to new ArticlesRepository(config, tracer, logger). Use cases and controllers don't notice — they get whatever the symbol currently resolves to.
This is also why the boundary stays clean: features don't import core-cms; the app passes the Payload config in.
The mock is reached from two directions. Both are legitimate, neither is "the test version":
BlogModule binds IArticlesRepository to MockArticlesRepository at module-load time. Anything resolving that symbol — use cases, controllers, tRPC procedures, the dev server — gets the mock until bindProductionBlog(config) swaps it for the real Payload-backed one. See §03.BlogModule binds IArticlesRepository to MockArticlesRepository at module-load time. Anything resolving that symbol — use cases, controllers, tRPC procedures, the dev server — gets the mock until bindProductionBlog(config, tracer, logger, bus, queue) swaps it for the real Payload-backed one. See §03.new MockArticlesRepository() and pass it directly into the use-case factory function. Same class, different consumer — just a closure with a fake repo.This is from packages/blog/src/di/module.ts — the very first binding in the module is the mock. Everything downstream (use cases, controllers) resolves through this default. bindProductionBlog(config) later replaces only this one line at app boot — use case + controller bindings stay put.
This is from packages/blog/src/di/module.ts — the very first binding in the module is the mock. Everything downstream (use cases, controllers) resolves through this default. bindProductionBlog(config, tracer, logger, bus, queue) later replaces only this one line at app boot — use case + controller bindings stay put.
export const BlogModule = new ContainerModule((bind) => { // 1) Mock is the DEFAULT binding for the repo symbol. // Dev server, unit tests, storybook all resolve to this. diff --git a/docs/architecture/di-explainer.html b/docs/architecture/di-explainer.html index 438438a..d6e0294 100644 --- a/docs/architecture/di-explainer.html +++ b/docs/architecture/di-explainer.html @@ -756,7 +756,7 @@ footer .colophon {file 04 · prod swapbind-production.ts
Replaces the mock repository binding with a real Payload-backed one at app boot.
-Exports
+bindProductionBlog(config: SanitizedConfig). Function body:blogContainer.unbind(symbol)if already bound, then.bind(symbol).toConstantValue(new ArticlesRepository(config)). Use cases and controllers stay bound to their factory bindings — they will fetch the new repo through the container automatically because their factories callctx.container.get(...)at every resolution.Exports
bindProductionBlog(config, tracer, logger, bus, queue). Function body:blogContainer.unbind(symbol)if already bound, then.bind(symbol).toConstantValue(new ArticlesRepository(config, tracer, logger)). Use cases and controllers are wrapped viawithSpan(withCapture(factory(deps)))at bind time so they inherit instrumentation without changing their factory bodies. Thebusandqueueparams come from the app'sresolveEventsAndJobs*step (ADR-015) and feed the// <gen:event-handlers>/// <gen:jobs>injection sites.When it runs: called from app boot (apps/web-next/src/server/bind-production.ts) whenUSE_DEV_SEED ≠ "true"AND Payload config is resolvable.