mirror of
https://github.com/juherr/kill-the-news.git
synced 2026-06-21 06:13:48 +00:00
refactor: separate Feed domain state from persistence DTO
Move four DDD tensions on the Feed aggregate to ground: - #1 The aggregate now holds a domain FeedState (camelCase) instead of the snake_case FeedConfig DTO; infrastructure/feed-mapper.ts owns the FeedState<->FeedConfig/FeedListItem translation as the sole snake_case site outside the HTTP edge. - #3 Replace the edit() recomputeExpiry control flag with a Lifetime VO: passing a lifetime recomputes expiry, omitting it preserves the current one (the dashboard quick-edit path). - #4 Domain events carry their own feedId; dispatchFeedEvents centralizes the drain+dispatch in the application layer (no more manual pullEvents at call sites), keeping infra->application dependency direction intact. - #6 Rename FeedId.fromTrusted to FeedId.unchecked to make the absence of revalidation explicit. Adds Lifetime + feed-mapper round-trip tests. 353 tests green, tsc clean, wrangler dry-run OK. Docs (CLAUDE.md) synced. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
import { FeedId } from "./value-objects/feed-id";
|
||||
|
||||
/**
|
||||
* Domain events the Feed aggregate records when it mutates. They describe *what
|
||||
* happened* in business terms; the application layer decides which side effects
|
||||
* to run (counters, WebSub pings, favicon caching) via a dispatcher. This keeps
|
||||
* the aggregate ignorant of infrastructure and the orchestration code free of
|
||||
* scattered, inline side effects.
|
||||
* happened* in business terms and carry their own `feedId`, so the application
|
||||
* dispatcher can route side effects (counters, WebSub pings, favicon caching)
|
||||
* without the caller threading the id back in. This keeps the aggregate ignorant
|
||||
* of infrastructure and the orchestration code free of scattered, inline effects.
|
||||
*
|
||||
* Only mutations that currently have side effects emit events — feed creation
|
||||
* and email ingestion. Edits and removals carry no side effect, so they emit
|
||||
@@ -12,5 +14,5 @@
|
||||
* outside this mechanism by design — they have no aggregate event to ride on.
|
||||
*/
|
||||
export type FeedEvent =
|
||||
| { type: "FeedCreated" }
|
||||
| { type: "EmailIngested"; iconDomain?: string };
|
||||
| { type: "FeedCreated"; feedId: FeedId }
|
||||
| { type: "EmailIngested"; feedId: FeedId; iconDomain?: string };
|
||||
|
||||
Reference in New Issue
Block a user