docs(plan-2): document constructor-injection pattern for payload repos

Revises Task 2.8's note: spec example used `import config from
'@repo/core-cms'` which creates a workspace dependency cycle (blog deps
on core-cms; core-cms deps on blog/cms). Constructor injection breaks the
cycle at the package graph. Apply to all payload-backed feature repos.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-04 22:32:01 +02:00
parent a92341fb74
commit 81fe4aa3b2

View File

@@ -1042,6 +1042,14 @@ export class PayloadArticlesRepository implements IArticlesRepository {
> Note: `as never` casts on the Payload `data` arguments are needed because Payload's generated types (which we don't have for the empty-collection core-cms config) would normally constrain these. With empty `collections: []`, the generated types don't include `'articles'`, so we cast through `never`. After Plan 3 wires articles into core-cms.collections AND `pnpm generate:types` runs, these casts can potentially be removed — but for Plan 2's purpose (decoupled feature with deferred wiring) the casts are correct.
> **Critical architectural note (revised after execution):** The repo takes `SanitizedConfig` via its constructor instead of `import config from '@repo/core-cms'` (which would create a workspace dependency cycle: blog ↔ core-cms). Constructor injection breaks the cycle at the package-graph level. The DI binding for production (Plan 5, app boot) supplies the config:
> ```ts
> import config from '@repo/core-cms'
> blogContainer.bind(BLOG_SYMBOLS.IArticlesRepository)
> .toDynamicValue(() => new PayloadArticlesRepository(config))
> ```
> The blog `package.json` does NOT declare `@repo/core-cms` as a dependency. Apply this pattern to every payload-backed feature repository.
- [ ] **Step 4: Run — expect pass**
Run: `cd packages/blog && pnpm vitest run src/infrastructure/repositories/payload-articles.repository.test.ts`