mirror of
https://github.com/svemagie/indiekit-endpoint-blogroll.git
synced 2026-04-02 15:34:59 +02:00
feat: add lastItemAt field — tracks newest item publish date per blog
Stores the most recent item's published date on the blog document during feed sync. Exposed in API response alongside lastFetchAt. Enables sorting/displaying blogs by content freshness rather than last fetch time.
This commit is contained in:
@@ -234,6 +234,7 @@ function sanitizeBlog(blog) {
|
|||||||
itemCount: blog.itemCount,
|
itemCount: blog.itemCount,
|
||||||
pinned: blog.pinned,
|
pinned: blog.pinned,
|
||||||
lastFetchAt: blog.lastFetchAt,
|
lastFetchAt: blog.lastFetchAt,
|
||||||
|
lastItemAt: blog.lastItemAt || null,
|
||||||
source: blog.source || null,
|
source: blog.source || null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ export async function createBlog(application, data) {
|
|||||||
author: data.author || null,
|
author: data.author || null,
|
||||||
status: "active",
|
status: "active",
|
||||||
lastFetchAt: null,
|
lastFetchAt: null,
|
||||||
|
lastItemAt: null,
|
||||||
lastError: null,
|
lastError: null,
|
||||||
itemCount: 0,
|
itemCount: 0,
|
||||||
pinned: data.pinned || false,
|
pinned: data.pinned || false,
|
||||||
@@ -200,6 +201,7 @@ export async function updateBlogStatus(application, id, status) {
|
|||||||
if (status.itemCount !== undefined) {
|
if (status.itemCount !== undefined) {
|
||||||
update.itemCount = status.itemCount;
|
update.itemCount = status.itemCount;
|
||||||
}
|
}
|
||||||
|
if (status.lastItemAt) update.lastItemAt = status.lastItemAt;
|
||||||
if (status.title) update.title = status.title;
|
if (status.title) update.title = status.title;
|
||||||
if (status.photo) update.photo = status.photo;
|
if (status.photo) update.photo = status.photo;
|
||||||
if (status.siteUrl) update.siteUrl = status.siteUrl;
|
if (status.siteUrl) update.siteUrl = status.siteUrl;
|
||||||
@@ -289,6 +291,7 @@ export async function upsertBlog(application, data) {
|
|||||||
if (data.skipItemFetch !== undefined) setFields.skipItemFetch = data.skipItemFetch;
|
if (data.skipItemFetch !== undefined) setFields.skipItemFetch = data.skipItemFetch;
|
||||||
if (data.photo !== undefined) setFields.photo = data.photo;
|
if (data.photo !== undefined) setFields.photo = data.photo;
|
||||||
if (data.lastFetchAt !== undefined) setFields.lastFetchAt = data.lastFetchAt;
|
if (data.lastFetchAt !== undefined) setFields.lastFetchAt = data.lastFetchAt;
|
||||||
|
if (data.lastItemAt !== undefined) setFields.lastItemAt = data.lastItemAt;
|
||||||
if (data.status !== undefined) setFields.status = data.status;
|
if (data.status !== undefined) setFields.status = data.status;
|
||||||
|
|
||||||
// $setOnInsert only for fields NOT already in $set (avoids MongoDB path conflicts)
|
// $setOnInsert only for fields NOT already in $set (avoids MongoDB path conflicts)
|
||||||
@@ -312,6 +315,7 @@ export async function upsertBlog(application, data) {
|
|||||||
if (!("skipItemFetch" in setFields)) insertDefaults.skipItemFetch = false;
|
if (!("skipItemFetch" in setFields)) insertDefaults.skipItemFetch = false;
|
||||||
if (!("photo" in setFields)) insertDefaults.photo = null;
|
if (!("photo" in setFields)) insertDefaults.photo = null;
|
||||||
if (!("lastFetchAt" in setFields)) insertDefaults.lastFetchAt = null;
|
if (!("lastFetchAt" in setFields)) insertDefaults.lastFetchAt = null;
|
||||||
|
if (!("lastItemAt" in setFields)) insertDefaults.lastItemAt = null;
|
||||||
if (!("status" in setFields)) insertDefaults.status = "active";
|
if (!("status" in setFields)) insertDefaults.status = "active";
|
||||||
|
|
||||||
const result = await collection.updateOne(
|
const result = await collection.updateOne(
|
||||||
|
|||||||
@@ -307,10 +307,19 @@ export async function syncBlogItems(application, blog, options = {}) {
|
|||||||
if (result.upserted) added++;
|
if (result.upserted) added++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute newest item publish date
|
||||||
|
let newestDate = null;
|
||||||
|
for (const item of feed.items) {
|
||||||
|
if (item.published && (!newestDate || item.published > newestDate)) {
|
||||||
|
newestDate = item.published;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update blog metadata
|
// Update blog metadata
|
||||||
const updateData = {
|
const updateData = {
|
||||||
success: true,
|
success: true,
|
||||||
itemCount: feed.items.length,
|
itemCount: feed.items.length,
|
||||||
|
lastItemAt: newestDate,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update title if not manually set (still has feedUrl as title)
|
// Update title if not manually set (still has feedUrl as title)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@rmdes/indiekit-endpoint-blogroll",
|
"name": "@rmdes/indiekit-endpoint-blogroll",
|
||||||
"version": "1.0.22",
|
"version": "1.0.23",
|
||||||
"description": "Blogroll endpoint for Indiekit. Aggregates blog feeds from OPML, JSON feeds, or manual entry.",
|
"description": "Blogroll endpoint for Indiekit. Aggregates blog feeds from OPML, JSON feeds, or manual entry.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"indiekit",
|
"indiekit",
|
||||||
|
|||||||
Reference in New Issue
Block a user