refactor(domain): introduce FeedRepository as the single KV access layer

Centralise the KV key schema and all get/put access behind a FeedRepository
class under src/domain/. Every feed/email/list/icon/websub/counter key was
previously inlined across ~12 modules with two divergent storeEmail and
addFeedToList implementations; the dead src/utils/storage.ts write path is
removed and the email key convention unified on feed:<id>:<ts>.

Behaviour-preserving: existing tests pass unchanged in logic, plus a new
feed-repository.test.ts covering CRUD, key builders, list ops and counters.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Julien Herr
2026-05-23 23:56:44 +02:00
parent a0eaebe749
commit 2b3f00f7e3
22 changed files with 616 additions and 539 deletions
+2 -4
View File
@@ -7,6 +7,7 @@ import {
import { waitUntilSafe } from "../utils/worker";
import { DEFAULT_LEASE_SECONDS, MAX_LEASE_SECONDS } from "../config/constants";
import { feedTopicPattern } from "../utils/urls";
import { FeedRepository } from "../domain/feed-repository";
type AppEnv = { Bindings: Env };
@@ -73,10 +74,7 @@ hubRouter.post("/", async (c) => {
const feedId = match[2];
// Verify the feed exists before accepting any subscription
const feedConfig = await env.EMAIL_STORAGE.get(
`feed:${feedId}:config`,
"json",
);
const feedConfig = await FeedRepository.from(env).getConfig(feedId);
if (!feedConfig) {
return c.text("Not Found: feed does not exist", 404);
}