diff --git a/lib/storage/blogs.js b/lib/storage/blogs.js index 33f7a99..e5ebac4 100644 --- a/lib/storage/blogs.js +++ b/lib/storage/blogs.js @@ -86,7 +86,7 @@ export async function getBlogByFeedUrl(application, feedUrl) { */ export async function createBlog(application, data) { const collection = getCollection(application); - const now = new Date(); + const now = new Date().toISOString(); const blog = { sourceId: data.sourceId ? new ObjectId(data.sourceId) : null, @@ -127,7 +127,7 @@ export async function updateBlog(application, id, data) { const update = { ...data, - updatedAt: new Date(), + updatedAt: new Date().toISOString(), }; // Remove fields that shouldn't be updated directly @@ -162,8 +162,8 @@ export async function deleteBlog(application, id) { $set: { status: "deleted", hidden: true, - deletedAt: new Date(), - updatedAt: new Date(), + deletedAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), }, } ); @@ -181,12 +181,12 @@ export async function updateBlogStatus(application, id, status) { const objectId = typeof id === "string" ? new ObjectId(id) : id; const update = { - updatedAt: new Date(), + updatedAt: new Date().toISOString(), }; if (status.success) { update.status = "active"; - update.lastFetchAt = new Date(); + update.lastFetchAt = new Date().toISOString(); update.lastError = null; if (status.itemCount !== undefined) { update.itemCount = status.itemCount; @@ -246,7 +246,7 @@ export async function getCategories(application) { */ export async function upsertBlog(application, data) { const collection = getCollection(application); - const now = new Date(); + const now = new Date().toISOString(); // Skip if a blog with this feedUrl was soft-deleted const deleted = await collection.findOne({ diff --git a/lib/storage/items.js b/lib/storage/items.js index 9e66101..0519b4b 100644 --- a/lib/storage/items.js +++ b/lib/storage/items.js @@ -206,7 +206,7 @@ export async function countItems(application, options = {}) { */ export async function upsertItem(application, data) { const collection = getCollection(application); - const now = new Date(); + const now = new Date().toISOString(); const result = await collection.updateOne( { blogId: new ObjectId(data.blogId), uid: data.uid }, diff --git a/lib/storage/sources.js b/lib/storage/sources.js index 6a01572..465fb3c 100644 --- a/lib/storage/sources.js +++ b/lib/storage/sources.js @@ -45,7 +45,7 @@ export async function getSource(application, id) { */ export async function createSource(application, data) { const collection = getCollection(application); - const now = new Date(); + const now = new Date().toISOString(); const source = { type: data.type, // "opml_url" | "opml_file" | "manual" | "json_feed" | "microsub" @@ -80,7 +80,7 @@ export async function updateSource(application, id, data) { const update = { ...data, - updatedAt: new Date(), + updatedAt: new Date().toISOString(), }; // Remove fields that shouldn't be updated directly @@ -135,11 +135,11 @@ export async function updateSourceSyncStatus(application, id, status) { const objectId = typeof id === "string" ? new ObjectId(id) : id; const update = { - updatedAt: new Date(), + updatedAt: new Date().toISOString(), }; if (status.success) { - update.lastSyncAt = new Date(); + update.lastSyncAt = new Date().toISOString(); update.lastSyncError = null; } else { update.lastSyncError = status.error; diff --git a/lib/sync/feed.js b/lib/sync/feed.js index a6e4084..b7803cc 100644 --- a/lib/sync/feed.js +++ b/lib/sync/feed.js @@ -142,8 +142,8 @@ function parseJsonFeed(content, feedUrl, maxItems) { text: item.content_text, }, summary: decodeEntities(item.summary) || truncateText(item.content_text, 300), - published: item.date_published ? new Date(item.date_published) : new Date(), - updated: item.date_modified ? new Date(item.date_modified) : undefined, + published: item.date_published ? new Date(item.date_published).toISOString() : new Date().toISOString(), + updated: item.date_modified ? new Date(item.date_modified).toISOString() : undefined, author: item.author || (item.authors?.[0]), photo: item.image ? [item.image] : undefined, categories: item.tags || [], @@ -168,6 +168,10 @@ function parseJsonFeed(content, feedUrl, maxItems) { function normalizeItem(item, feedUrl) { const description = item.description || item.summary || ""; + // Convert dates to ISO strings - feedparser returns Date objects + const published = item.pubdate || item.date; + const updated = item.date; + return { uid: generateUid(feedUrl, item.guid || item.link), url: item.link || item.origlink, @@ -177,8 +181,8 @@ function normalizeItem(item, feedUrl) { text: stripHtml(description), }, summary: truncateText(stripHtml(item.summary || description), 300), - published: item.pubdate || item.date || new Date(), - updated: item.date, + published: published ? (published instanceof Date ? published.toISOString() : new Date(published).toISOString()) : new Date().toISOString(), + updated: updated ? (updated instanceof Date ? updated.toISOString() : new Date(updated).toISOString()) : undefined, author: item.author ? { name: item.author } : undefined, photo: extractPhotos(item), categories: item.categories || [], diff --git a/lib/sync/microsub.js b/lib/sync/microsub.js index 890b747..8c0e606 100644 --- a/lib/sync/microsub.js +++ b/lib/sync/microsub.js @@ -100,8 +100,8 @@ export async function syncMicrosubSource(application, source) { $set: { status: "deleted", hidden: true, - deletedAt: new Date(), - updatedAt: new Date(), + deletedAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), }, } ); @@ -227,8 +227,8 @@ export async function handleMicrosubWebhook(application, data) { { $set: { status: "inactive", - unsubscribedAt: new Date(), - updatedAt: new Date(), + unsubscribedAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), }, } ); diff --git a/lib/sync/scheduler.js b/lib/sync/scheduler.js index a320e73..d499f72 100644 --- a/lib/sync/scheduler.js +++ b/lib/sync/scheduler.js @@ -110,7 +110,7 @@ export async function runFullSync(application, options = {}) { { $set: { key: "syncStats", - lastFullSync: new Date(), + lastFullSync: new Date().toISOString(), duration, sources: { total: enabledSources.length, diff --git a/package.json b/package.json index de3b18b..d818e64 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@rmdes/indiekit-endpoint-blogroll", - "version": "1.0.16", + "version": "1.0.17", "description": "Blogroll endpoint for Indiekit. Aggregates blog feeds from OPML, JSON feeds, or manual entry.", "keywords": [ "indiekit",