@indiekit/endpoint-syndicate
Version:
Syndication endpoint for Indiekit. Provides an endpoint you can ping to check that recently published posts have been posted to configured syndication targets.
111 lines (100 loc) • 3.42 kB
JavaScript
/**
* Get post data
* @param {object} postsCollection - Posts database collection
* @param {string} url - URL of existing post (optional)
* @returns {Promise<object>} Post data for given URL else recently published post
*/
export const getPostData = async (postsCollection, url) => {
let postData = {};
if (url) {
// Get item in database which matching URL
postData = await postsCollection.findOne({
"properties.url": url,
});
} else {
// Get published posts awaiting syndication and return first item
const items = await postsCollection
.find({
"properties.mp-syndicate-to": {
$exists: true,
},
"properties.syndication": {
$exists: false,
},
"properties.post-status": {
$ne: "draft",
},
})
// eslint-disable-next-line unicorn/no-array-sort
.sort({ "properties.published": -1 })
.limit(1)
.toArray();
postData = items[0];
}
return postData;
};
/**
* Check if target already returned a syndication URL
* @param {Array} syndicatedUrls - Syndication URLs
* @param {string} syndicateTo - Syndication target
* @returns {boolean} Target returned a syndication URL
*/
export const hasSyndicationUrl = (syndicatedUrls, syndicateTo) => {
return syndicatedUrls.some((url) => {
const { origin } = new URL(url);
return syndicateTo.includes(origin);
});
};
/**
* Get syndication target for syndication URL
* @param {Array} syndicationTargets - Publication syndication targets
* @param {string} syndicateTo - Syndication URL
* @returns {object|undefined} Publication syndication target
*/
export const getSyndicationTarget = (syndicationTargets, syndicateTo) => {
return syndicationTargets.find((target) => {
if (!target?.info?.uid) {
return;
}
const targetOrigin = new URL(target.info.uid).origin;
const syndicateToOrigin = new URL(syndicateTo).origin;
return targetOrigin === syndicateToOrigin;
});
};
/**
* Syndicate URLs to configured syndication targets
* @param {object} publication - Publication configuration
* @param {object} properties - JF2 properties
* @returns {Promise<object>} Syndication target
*/
export const syndicateToTargets = async (publication, properties) => {
const { syndicationTargets } = publication;
const syndicateTo = properties["mp-syndicate-to"];
const syndicateToUrls = Array.isArray ? syndicateTo : [syndicateTo];
const syndicatedUrls = properties.syndication || [];
const failedTargets = [];
for (const url of syndicateToUrls) {
const target = getSyndicationTarget(syndicationTargets, url);
const alreadySyndicated = hasSyndicationUrl(syndicatedUrls, url);
if (target && !alreadySyndicated) {
try {
const syndicatedUrl = await target.syndicate(properties, publication);
if (syndicatedUrl) {
// Add syndicated URL to list of syndicated URLs
syndicatedUrls.push(syndicatedUrl);
} else {
// Add failed syndication target to list of failed targets
failedTargets.push(target.info.uid);
}
} catch (error) {
// Add failed syndication target to list of failed targets
failedTargets.push(target.info.uid);
console.error(error.message);
}
}
}
return {
...(failedTargets.length > 0 && { failedTargets }),
syndicatedUrls,
};
};