/** * * @param {any} str */ function log(str) { console.log(JSON.stringify(str, undefined, 4)) } /** * convert object to string * @param {any} obj object */ function obj2str(obj) { if (Array.isArray(obj)) { return JSON.stringify( obj.map(function (idx) { return obj2str(idx) }) ) } else if (typeof obj === "object" && obj !== null) { var elements = Object.keys(obj) .sort() .map(function (key) { var val = obj2str(obj[key]) if (val) { return key + ":" + val } }) var elementsCleaned = [] for (var i = 0; i < elements.length; i++) { if (elements[i]) elementsCleaned.push(elements[i]) } return "{" + elementsCleaned.join("|") + "}" } if (obj) return obj } var { LIGHTHOUSE_TOKEN } = require("../config") /** * clear SSR cache * @returns {number} */ function clearSSRCache() { var info = context.db.deleteMany("ssr", {}) context.response.header("X-SSR-Cleared", info.removed) return info.removed } function calculateAverageDynamically(dbObjs) { const sumObj = {} let count = 0 dbObjs.forEach((obj) => { accumulate(obj, sumObj) count++ }) function accumulate(sourceObj, targetObj) { for (const key in sourceObj) { if (typeof sourceObj[key] === "number") { targetObj[key] = (targetObj[key] || 0) + sourceObj[key] } else if (typeof sourceObj[key] === "object" && sourceObj[key] !== null) { targetObj[key] = targetObj[key] || {} accumulate(sourceObj[key], targetObj[key]) } } } function average(targetObj) { for (const key in targetObj) { if (typeof targetObj[key] === "number") { targetObj[key] = targetObj[key] / count } else if (typeof targetObj[key] === "object") { average(targetObj[key]) } } } average(sumObj) return sumObj } function run(url) { const response = context.http .fetch(url, { timeout: 300, method: "GET", headers: { "Content-Type": "application/json", }, }) .body.json() // needs enough traffic to be collected const cruxMetrics = { "First Contentful Paint": response?.loadingExperience?.metrics?.FIRST_CONTENTFUL_PAINT_MS?.category, "First Input Delay": response?.loadingExperience?.metrics?.FIRST_INPUT_DELAY_MS?.category, } const lighthouse = response.lighthouseResult const lighthouseMetrics = { FCPS: lighthouse.audits["first-contentful-paint"].score * 100, FCPV: lighthouse.audits["first-contentful-paint"].numericValue / 1000, FMPS: lighthouse.audits["first-meaningful-paint"].score * 100, FMPV: lighthouse.audits["first-meaningful-paint"].numericValue / 1000, SIS: lighthouse.audits["speed-index"].score * 100, SIV: lighthouse.audits["speed-index"].numericValue / 1000, TTIS: lighthouse.audits["interactive"].score * 100, TTIV: lighthouse.audits["interactive"].numericValue / 1000, FPIDS: lighthouse.audits["max-potential-fid"].score * 100, FPIDV: lighthouse.audits["max-potential-fid"].numericValue / 1000, } let dbObject = { cruxMetrics, lighthouseMetrics, performance: Math.round(lighthouse.categories.performance.score * 100), accessibility: Math.round(lighthouse.categories.accessibility.score * 100), bestPractices: Math.round(lighthouse.categories["best-practices"].score * 100), seo: Math.round(lighthouse.categories.seo.score * 100), } return dbObject } function setUpQuery(subPath = "/") { const api = "https://www.googleapis.com/pagespeedonline/v5/runPagespeed" let params = `category=performance&category=accessibility&category=best-practices&category=seo` const parameters = { url: encodeURIComponent(`https://allkids-erfurt.de/${subPath}`), key: LIGHTHOUSE_TOKEN, } let query = `${api}?` for (let key in parameters) { query += `${key}=${parameters[key]}&` } query += params // Append other parameters without URL encoding return query } module.exports = { log, clearSSRCache, obj2str, run, setUpQuery, calculateAverageDynamically, }