feat(app): wire bindAll() + bindAllDevSeed() dispatcher; add DI explainer page
apps/web-next/src/server/bind-production.ts now exports three functions: - bindAllProduction() — production-only binders - bindAllDevSeed() — dev-seed-only binders (NEW, calls all 5 features) - bindAll() — dispatcher that branches on USE_DEV_SEED env var All page/route callers (page.tsx, about/page.tsx, blog/[slug]/page.tsx, api/trpc/[trpc]/route.ts) updated from bindAllProduction → bindAll so the env flag actually has effect. docs/architecture/di-explainer.html (NEW): standalone interactive page explaining the di/ folder file-by-file, the loading sequence (8 stages), the three binding kinds (.to / .toDynamicValue / .toConstantValue), an interactive three-mode picker showing how the same blogContainer state differs across default/dev-seed/production, a conditions table, and a final card on how tests bypass DI entirely. Sister page to data-flow-explainer.html. Refactor log entry + canonical doc updates follow in subsequent commits.
This commit is contained in:
@@ -5,9 +5,18 @@ import { bindProductionAuth } from "@repo/auth/di/bind-production";
|
||||
import { bindProductionMarketingPages } from "@repo/marketing-pages/di/bind-production";
|
||||
import { bindProductionNavigation } from "@repo/navigation/di/bind-production";
|
||||
import { bindProductionMedia } from "@repo/media/di/bind-production";
|
||||
import { bindDevSeedBlog } from "@repo/blog/di/bind-dev-seed";
|
||||
import { bindDevSeedAuth } from "@repo/auth/di/bind-dev-seed";
|
||||
import { bindDevSeedMarketingPages } from "@repo/marketing-pages/di/bind-dev-seed";
|
||||
import { bindDevSeedNavigation } from "@repo/navigation/di/bind-dev-seed";
|
||||
import { bindDevSeedMedia } from "@repo/media/di/bind-dev-seed";
|
||||
|
||||
let bound = false;
|
||||
|
||||
/**
|
||||
* Production path: swap each feature's mock repository binding for the real
|
||||
* Payload-backed one. Constructs `new XRepository(config)` per feature.
|
||||
*/
|
||||
export async function bindAllProduction(): Promise<void> {
|
||||
if (bound) return;
|
||||
bound = true;
|
||||
@@ -18,3 +27,35 @@ export async function bindAllProduction(): Promise<void> {
|
||||
bindProductionNavigation(resolvedConfig);
|
||||
bindProductionMedia(resolvedConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dev-seed path: keep each feature's MockXRepository in place but populate it
|
||||
* with realistic seed data so the running app shows non-empty UI without
|
||||
* Payload booted. Useful for storybook, design review, and offline dev.
|
||||
*
|
||||
* Mutually exclusive with `bindAllProduction()` — both rebind the same symbols.
|
||||
*/
|
||||
export async function bindAllDevSeed(): Promise<void> {
|
||||
if (bound) return;
|
||||
bound = true;
|
||||
await bindDevSeedAuth();
|
||||
await bindDevSeedBlog();
|
||||
await bindDevSeedMarketingPages();
|
||||
await bindDevSeedNavigation();
|
||||
await bindDevSeedMedia();
|
||||
}
|
||||
|
||||
/**
|
||||
* Boot dispatcher: pick the binder based on `process.env.USE_DEV_SEED`.
|
||||
* Idempotent — guarded by the same `bound` flag as `bindAllProduction`.
|
||||
*
|
||||
* Call this from server entry points (route handlers, page server components)
|
||||
* before resolving any feature controller.
|
||||
*/
|
||||
export async function bindAll(): Promise<void> {
|
||||
if (process.env.USE_DEV_SEED === "true") {
|
||||
await bindAllDevSeed();
|
||||
return;
|
||||
}
|
||||
await bindAllProduction();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user