mirror of
https://github.com/juherr/kill-the-news.git
synced 2026-06-21 06:13:48 +00:00
2a3aeb8a18
Add a "Public page" link next to the Rendered/Raw toggle in the admin email view, opening the standalone /entries/:feedId/:entryId render. Centralize the entry route shape in a pure entryPath() builder, used by both the admin link and the RSS/Atom/JSON feed generator. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
73 lines
2.2 KiB
TypeScript
73 lines
2.2 KiB
TypeScript
import { Env } from "../types";
|
|
import { MailboxId } from "../domain/value-objects/mailbox-id";
|
|
|
|
export function baseUrl(env: Env): string {
|
|
return `https://${env.DOMAIN}`;
|
|
}
|
|
|
|
export function feedRssUrl(feedId: string, env: Env): string {
|
|
return `${baseUrl(env)}/rss/${feedId}`;
|
|
}
|
|
|
|
export function feedAtomUrl(feedId: string, env: Env): string {
|
|
return `${baseUrl(env)}/atom/${feedId}`;
|
|
}
|
|
|
|
export function feedJsonUrl(feedId: string, env: Env): string {
|
|
return `${baseUrl(env)}/json/${feedId}`;
|
|
}
|
|
|
|
/** Path of an email's public HTML view. The single source of truth for the
|
|
* `/entries/:feedId/:entryId` route shape (entryId = the email's receivedAt). */
|
|
export function entryPath(feedId: string, receivedAt: number): string {
|
|
return `/entries/${feedId}/${receivedAt}`;
|
|
}
|
|
|
|
export function feedUrl(
|
|
format: "rss" | "atom",
|
|
feedId: string,
|
|
env: Env,
|
|
): string {
|
|
return format === "rss" ? feedRssUrl(feedId, env) : feedAtomUrl(feedId, env);
|
|
}
|
|
|
|
export type FeedFormat = "rss" | "atom" | "json";
|
|
|
|
export function feedFormatUrl(
|
|
format: FeedFormat,
|
|
feedId: string,
|
|
env: Env,
|
|
): string {
|
|
if (format === "atom") return feedAtomUrl(feedId, env);
|
|
if (format === "json") return feedJsonUrl(feedId, env);
|
|
return feedRssUrl(feedId, env);
|
|
}
|
|
|
|
/**
|
|
* Link to a third-party validator for the public feed URL: the W3C Feed
|
|
* Validator for RSS/Atom, validator.jsonfeed.org for JSON Feed. Used in the
|
|
* admin UI so an operator can confirm a feed parses in real readers.
|
|
*/
|
|
export function feedValidatorUrl(
|
|
format: FeedFormat,
|
|
feedId: string,
|
|
env: Env,
|
|
): string {
|
|
const encoded = encodeURIComponent(feedFormatUrl(format, feedId, env));
|
|
return format === "json"
|
|
? `https://validator.jsonfeed.org/?url=${encoded}`
|
|
: `https://validator.w3.org/feed/check.cgi?url=${encoded}`;
|
|
}
|
|
|
|
export function feedEmailAddress(mailboxId: string, env: Env): string {
|
|
// The mailbox→address shape lives on the VO; this edge only resolves the domain.
|
|
return MailboxId.unchecked(mailboxId).emailAddress(
|
|
env.EMAIL_DOMAIN ?? env.DOMAIN,
|
|
);
|
|
}
|
|
|
|
export function feedTopicPattern(env: Env): RegExp {
|
|
const escaped = env.DOMAIN.replaceAll(".", "\\.");
|
|
return new RegExp(`^https://${escaped}/(rss|atom)/([^/]+)$`);
|
|
}
|