From bdfc122beb31be761c05ae5d1623d35559195dfb Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Thu, 12 Jun 2025 21:16:26 -0500 Subject: [PATCH] Refactor json/xml code --- app/feed.json/route.ts | 16 +++------------- app/rss.xml/route.ts | 35 +++++------------------------------ src/feed/json.ts | 12 +++++++++++- src/feed/rss.ts | 29 ++++++++++++++++++++++++----- 4 files changed, 43 insertions(+), 49 deletions(-) diff --git a/app/feed.json/route.ts b/app/feed.json/route.ts index 156ddb42..ccf72a08 100644 --- a/app/feed.json/route.ts +++ b/app/feed.json/route.ts @@ -1,11 +1,7 @@ import { getPhotosCached } from '@/photo/cache'; -import { - BASE_URL, - SITE_FEEDS_ENABLED, - META_TITLE, -} from '@/app/config'; +import { SITE_FEEDS_ENABLED } from '@/app/config'; import { FEED_PHOTO_REQUEST_LIMIT } from '@/feed'; -import { formatPhotoForFeedJson } from '@/feed/json'; +import { formatFeedJson } from '@/feed/json'; // Cache for 24 hours export const revalidate = 86_400; @@ -16,13 +12,7 @@ export async function GET() { limit: FEED_PHOTO_REQUEST_LIMIT, sortBy: 'createdAt', }); - return Response.json({ - meta: { - title: META_TITLE, - url: BASE_URL, - }, - photos: photos.map(formatPhotoForFeedJson), - }); + return Response.json(formatFeedJson(photos)); } else { return new Response('Feed disabled', { status: 404 }); } diff --git a/app/rss.xml/route.ts b/app/rss.xml/route.ts index 25a0a952..d559818a 100644 --- a/app/rss.xml/route.ts +++ b/app/rss.xml/route.ts @@ -1,13 +1,7 @@ import { getPhotosCached } from '@/photo/cache'; -import { - BASE_URL, - META_DESCRIPTION, - META_TITLE, - SITE_FEEDS_ENABLED, -} from '@/app/config'; +import { SITE_FEEDS_ENABLED } from '@/app/config'; import { FEED_PHOTO_REQUEST_LIMIT } from '@/feed'; -import { createRssItems } from '@/feed/rss'; -import { ABSOLUTE_PATH_FOR_RSS_XML } from '@/app/paths'; +import { formatFeedRss } from '@/feed/rss'; // Cache for 24 hours export const revalidate = 86_400; @@ -19,28 +13,9 @@ export async function GET() { sortBy: 'createdAt', }); - const items = createRssItems(photos); - - return new Response(` - - - ${META_TITLE} - - ${BASE_URL} - ${META_DESCRIPTION} - ${items.join('\n')} - - - `, - { headers: { 'Content-Type': 'text/xml' } }, + return new Response( + formatFeedRss(photos), + { headers: { 'Content-Type': 'text/xml' } }, ); } else { return new Response('Feed disabled', { status: 404 }); diff --git a/src/feed/json.ts b/src/feed/json.ts index 9a1fe608..750442f9 100644 --- a/src/feed/json.ts +++ b/src/feed/json.ts @@ -9,6 +9,8 @@ import { } from '.'; import { formatDateFromPostgresString } from '@/utility/date'; import { Photo } from '@/photo'; +import { BASE_URL } from '@/app/config'; +import { META_TITLE } from '@/app/config'; interface FeedPhotoJson { id: string @@ -21,7 +23,7 @@ interface FeedPhotoJson { src: Record<'small' | 'medium' | 'large', FeedMedia> } -export const formatPhotoForFeedJson = (photo: Photo): FeedPhotoJson => ({ +const formatPhotoForFeedJson = (photo: Photo): FeedPhotoJson => ({ ...getCoreFeedFields(photo), url: absolutePathForPhoto({ photo }), ...photo.make && { make: photo.make }, @@ -34,3 +36,11 @@ export const formatPhotoForFeedJson = (photo: Photo): FeedPhotoJson => ({ large: generateFeedMedia(photo, FEED_PHOTO_WIDTH_LARGE), }, }); + +export const formatFeedJson = (photos: Photo[]) => ({ + meta: { + title: META_TITLE, + url: BASE_URL, + }, + photos: photos.map(formatPhotoForFeedJson), +}); diff --git a/src/feed/rss.ts b/src/feed/rss.ts index e34e9d1e..56e53e42 100644 --- a/src/feed/rss.ts +++ b/src/feed/rss.ts @@ -6,9 +6,10 @@ import { generateFeedMedia, getCoreFeedFields, } from '.'; -import { absolutePathForPhoto } from '@/app/paths'; +import { ABSOLUTE_PATH_FOR_RSS_XML, absolutePathForPhoto } from '@/app/paths'; import { formatDate } from '@/utility/date'; import { formatStringForXml } from '@/utility/string'; +import { BASE_URL, META_DESCRIPTION, META_TITLE } from '@/app/config'; interface FeedPhotoRss { id: string @@ -30,11 +31,12 @@ const formatPhotoForFeedRss = (photo: Photo): FeedPhotoRss => ({ }); const feedPhotoToXml = (photo: FeedPhotoRss): string => { - const formattedDate = formatDate({ date: photo.pubDate, length: 'rss' }); return ` ${photo.title} ${photo.link} - ${formattedDate} + + ${formatDate({ date: photo.pubDate, length: 'rss' })} + ${photo.link} ${photo.description ? `` @@ -55,5 +57,22 @@ const feedPhotoToXml = (photo: FeedPhotoRss): string => { `; }; -export const createRssItems = (photos: Photo[]) => - photos.map(formatPhotoForFeedRss).map(feedPhotoToXml); +export const formatFeedRss = (photos: Photo[]) => + ` + + + ${META_TITLE} + + ${BASE_URL} + ${META_DESCRIPTION} + ${photos.map(formatPhotoForFeedRss).map(feedPhotoToXml).join('\n')} + + `;