docs(dev-seed): canonical doc updates + refactor-log entry

- CLAUDE.md Key Conventions: 'App bootstrap' rule rewritten as 'Three
  binding modes per feature' — describes USE_DEV_SEED + NODE_ENV
  resolution order and the new ./di/bind-dev-seed export.
- AGENTS.md (root): exports list now mentions ./ui + ./di/bind-dev-seed;
  Per-feature public-API surface table gains a row; Apps section shows
  the bindAll() dispatcher with three-rule logic.
- docs/architecture/vertical-feature-spec.md §6: file shape now
  includes bind-dev-seed.ts, bind-dev-seed.test.ts, __seeds__/dev.ts;
  package.json exports list updated to include ./di/bind-dev-seed.
- docs/architecture/data-flow-explainer.html: anatomy tree gains
  __seeds__/ row; LAYERS.di description updated with new binders +
  cross-link to di-explainer.html; new LAYERS.seeds entry; public-
  surface card expanded to six subpaths.
- docs/superpowers/refactor-logs/2026-05-06-input-output-unification.md
  §7: new 'Post-Plan-9: dev-seed binders' entry summarizing the rollout
  (commits, per-feature additions, app wiring, tests, turbo, docs).
- bind-production.test.ts: dispatcher tests use vi.stubEnv (typesafe
  way to test process.env in TypeScript 5+ with @types/node read-only
  process.env types). 4 dispatcher tests + 2 bindAllProduction tests
  = 7 tests total.
This commit is contained in:
2026-05-06 19:49:58 +02:00
parent 6bf19f35c5
commit 8f34daca36
6 changed files with 99 additions and 43 deletions

View File

@@ -12,9 +12,6 @@ vi.mock("@repo/marketing-pages/di/bind-dev-seed", () => ({ bindDevSeedMarketingP
vi.mock("@repo/navigation/di/bind-dev-seed", () => ({ bindDevSeedNavigation: vi.fn() }));
vi.mock("@repo/media/di/bind-dev-seed", () => ({ bindDevSeedMedia: vi.fn() }));
const ORIGINAL_USE_DEV_SEED = process.env.USE_DEV_SEED;
const ORIGINAL_NODE_ENV = process.env.NODE_ENV;
describe("bindAllProduction", () => {
beforeEach(() => {
vi.resetModules();
@@ -51,26 +48,16 @@ describe("bindAll dispatcher", () => {
beforeEach(() => {
vi.resetModules();
vi.clearAllMocks();
delete process.env.USE_DEV_SEED;
delete process.env.NODE_ENV;
vi.unstubAllEnvs();
});
afterEach(() => {
if (ORIGINAL_USE_DEV_SEED === undefined) {
delete process.env.USE_DEV_SEED;
} else {
process.env.USE_DEV_SEED = ORIGINAL_USE_DEV_SEED;
}
if (ORIGINAL_NODE_ENV === undefined) {
delete process.env.NODE_ENV;
} else {
process.env.NODE_ENV = ORIGINAL_NODE_ENV;
}
vi.unstubAllEnvs();
});
it("USE_DEV_SEED='true' wins → dispatches to bindAllDevSeed", async () => {
process.env.USE_DEV_SEED = "true";
process.env.NODE_ENV = "production"; // even in production, dev seed wins
vi.stubEnv("USE_DEV_SEED", "true");
vi.stubEnv("NODE_ENV", "production"); // even in production, dev seed wins
const { bindAll } = await import("./bind-production");
const { bindDevSeedBlog } = await import("@repo/blog/di/bind-dev-seed");
const { bindProductionBlog } = await import("@repo/blog/di/bind-production");
@@ -82,7 +69,7 @@ describe("bindAll dispatcher", () => {
});
it("NODE_ENV='production' (no override) → dispatches to bindAllProduction", async () => {
process.env.NODE_ENV = "production";
vi.stubEnv("NODE_ENV", "production");
const { bindAll } = await import("./bind-production");
const { bindProductionBlog } = await import("@repo/blog/di/bind-production");
const { bindDevSeedBlog } = await import("@repo/blog/di/bind-dev-seed");
@@ -94,18 +81,7 @@ describe("bindAll dispatcher", () => {
});
it("NODE_ENV='development' → dispatches to bindAllDevSeed (developer default)", async () => {
process.env.NODE_ENV = "development";
const { bindAll } = await import("./bind-production");
const { bindDevSeedBlog } = await import("@repo/blog/di/bind-dev-seed");
const { bindProductionBlog } = await import("@repo/blog/di/bind-production");
await bindAll();
expect(bindDevSeedBlog).toHaveBeenCalledOnce();
expect(bindProductionBlog).not.toHaveBeenCalled();
});
it("NODE_ENV unset → dispatches to bindAllDevSeed (developer default)", async () => {
vi.stubEnv("NODE_ENV", "development");
const { bindAll } = await import("./bind-production");
const { bindDevSeedBlog } = await import("@repo/blog/di/bind-dev-seed");
const { bindProductionBlog } = await import("@repo/blog/di/bind-production");
@@ -117,8 +93,8 @@ describe("bindAll dispatcher", () => {
});
it("USE_DEV_SEED='false' is treated as not-set (only 'true' triggers dev seed)", async () => {
process.env.USE_DEV_SEED = "false";
process.env.NODE_ENV = "production";
vi.stubEnv("USE_DEV_SEED", "false");
vi.stubEnv("NODE_ENV", "production");
const { bindAll } = await import("./bind-production");
const { bindProductionBlog } = await import("@repo/blog/di/bind-production");
const { bindDevSeedBlog } = await import("@repo/blog/di/bind-dev-seed");