rittenhop-dev/versions/5.94.2/core/frontend/helpers/recommendations.js
2024-09-23 19:40:12 -04:00

117 lines
3.2 KiB
JavaScript

/* Recommendations helper
* Usage: `{{recommendations}}`
*
* Renders the template defined in `tpl/recommendations.hbs`
* Can be overridden by themes by uploading a partial under `partials/recommendations.hbs`
*
* Available options: limit, order, filter, page
*/
const {config, api, prepareContextResource, settingsCache} = require('../services/proxy');
const {templates, hbs} = require('../services/handlebars');
const logging = require('@tryghost/logging');
const errors = require('@tryghost/errors');
const createFrame = hbs.handlebars.createFrame;
/**
* Call the Recommendation Content API's browse method
* @param {Object} apiOptions
* @returns {Promise<Object>}
*/
async function fetchRecommendations(apiOptions) {
let timer;
try {
const controller = api.recommendationsPublic;
let response;
const logLevel = config.get('optimization:getHelper:timeout:level') || 'error';
const threshold = config.get('optimization:getHelper:timeout:threshold') || 5000;
const apiResponse = controller.browse(apiOptions);
const timeout = new Promise((resolve) => {
timer = setTimeout(() => {
logging[logLevel](new errors.HelperWarning({
message: `{{#recommendations}} took longer than ${threshold}ms and was aborted`,
code: 'ABORTED_RECOMMENDATIONS_HELPER',
errorDetails: {
api: 'recommendationsPublic.browse',
apiOptions
}
}));
resolve({recommendations: []});
}, threshold);
});
response = await Promise.race([apiResponse, timeout]);
clearTimeout(timer);
return response;
} catch (err) {
clearTimeout(timer);
throw err;
}
}
/**
* Parse Options
*
* @param {Object} options
* @returns {*}
*/
function parseOptions(options) {
let limit = options.limit ?? 5;
let order = options.order ?? 'created_at desc';
let filter = options.filter ?? '';
let page = options.page ?? 1;
return {
limit,
order,
filter,
page
};
}
/**
*
* @param {object} options
* @returns {Promise<any>}
*/
module.exports = async function recommendations(options) {
const recommendationsEnabled = settingsCache.get('recommendations_enabled');
if (!recommendationsEnabled) {
return;
}
options = options || {};
options.hash = options.hash || {};
options.data = options.data || {};
const data = createFrame(options.data);
let apiOptions = options.hash;
apiOptions = parseOptions(apiOptions);
try {
const response = await fetchRecommendations(apiOptions);
if (response.recommendations && response.recommendations.length) {
response.recommendations.forEach(prepareContextResource);
}
if (response.meta && response.meta.pagination) {
response.pagination = response.meta.pagination;
}
return templates.execute('recommendations', response, {data});
} catch (error) {
logging.error(error);
return null;
}
};
module.exports.async = true;