mirror of
https://github.com/svemagie/indiekit-endpoint-blogroll.git
synced 2026-04-02 15:34:59 +02:00
fix: store dates as ISO strings instead of Date objects
Prevents dateString.split crash when Nunjucks | date filter receives Date objects from MongoDB. All stored dates now use .toISOString(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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({
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 || [],
|
||||
|
||||
@@ -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(),
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user