UNPKG

@pierrad/web-carbon-analyzer

Version:

A tool to measure the carbon footprint of websites using CO2.js

177 lines 6.97 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); /** * Output Formatter module * Formats calculation results into structured output */ const logger_1 = __importDefault(require("../utils/logger")); const default_1 = __importDefault(require("../config/default")); class OutputFormatter { constructor(customConfig = {}) { this.config = { ...default_1.default.output, ...customConfig }; } /** * Format calculation results as a structured object * @param {string} url - The URL that was analyzed * @param {ResourcesData} resourcesData - Resource data from the NetworkInterceptor * @param {EmissionsData} emissionsData - Emissions data from the CO2Calculator * @param {Object} metadata - Additional metadata about the analysis * @returns {FormattedResults} - Formatted results */ formatResults(url, resourcesData, emissionsData, metadata = {}) { logger_1.default.info('Formatting output results'); // Create metadata section const formattedResults = { metadata: { url, timestamp: new Date().toISOString(), duration: resourcesData.totalDuration, configuration: metadata.configuration || {}, ...metadata }, // Create summary section summary: { totalEmissions: this.roundNumber(emissionsData.totalEmissions), totalSize: resourcesData.totalSize, totalRequests: resourcesData.totalResources, percentageGreen: this.calculateGreenPercentage(emissionsData), comparisons: this.formatComparisons(emissionsData.comparisons) }, // Create breakdowns section breakdowns: { byType: this.formatTypeBreakdown(emissionsData.byType), byDomain: this.formatDomainBreakdown(emissionsData.byDomain), byHosting: this.formatHostingBreakdown(emissionsData.byGreenHosting) } }; // Add detailed resources if configured if (this.config.includeResourceDetails) { formattedResults.resources = this.formatResourceDetails(emissionsData.perResource); } logger_1.default.info('Output formatting completed'); return formattedResults; } /** * Calculate the percentage of green-hosted resources * @param {EmissionsData} emissionsData - Emissions data * @returns {number} - Percentage of green-hosted resources (by size) */ calculateGreenPercentage(emissionsData) { const green = emissionsData.byGreenHosting.green.size || 0; const nonGreen = emissionsData.byGreenHosting.nonGreen.size || 0; const unknown = emissionsData.byGreenHosting.unknown.size || 0; const total = green + nonGreen + unknown; if (total === 0) { return 0; } return this.roundNumber((green / total) * 100); } /** * Format the resource type breakdown * @param {Record<string, TypeEmissions>} typeData - Breakdown by resource type * @returns {Record<string, TypeEmissions>} - Formatted breakdown */ formatTypeBreakdown(typeData) { const result = {}; for (const [type, data] of Object.entries(typeData)) { result[type] = { size: data.size, emissions: this.roundNumber(data.emissions), count: data.count }; } return result; } /** * Format the domain breakdown * @param {Record<string, DomainEmissions>} domainData - Breakdown by domain * @returns {Record<string, DomainEmissions>} - Formatted breakdown */ formatDomainBreakdown(domainData) { const result = {}; for (const [domain, data] of Object.entries(domainData)) { result[domain] = { size: data.size, emissions: this.roundNumber(data.emissions), count: data.count, isGreen: data.isGreen }; } return result; } /** * Format the green hosting breakdown * @param {Object} hostingData - Breakdown by hosting type * @returns {Object} - Formatted breakdown */ formatHostingBreakdown(hostingData) { return { green: { size: hostingData.green.size, emissions: this.roundNumber(hostingData.green.emissions), count: hostingData.green.count }, nonGreen: { size: hostingData.nonGreen.size, emissions: this.roundNumber(hostingData.nonGreen.emissions), count: hostingData.nonGreen.count }, unknown: { size: hostingData.unknown.size, emissions: this.roundNumber(hostingData.unknown.emissions), count: hostingData.unknown.count } }; } /** * Format the detailed resource list * @param {ResourceEmissions[]} resourcesData - List of resource emissions data * @returns {ResourceEmissions[]} - Formatted resource list */ formatResourceDetails(resourcesData) { return resourcesData.map(resource => ({ ...resource, emissions: this.roundNumber(resource.emissions) })); } /** * Format the human-readable comparisons * @param {Comparisons} comparisons - Comparison metrics * @returns {Comparisons} - Formatted comparisons */ formatComparisons(comparisons) { return { treeSeconds: this.roundNumber(comparisons.treeSeconds), carMeters: this.roundNumber(comparisons.carMeters), smartphoneCharges: this.roundNumber(comparisons.smartphoneCharges), waterBoiledML: this.roundNumber(comparisons.waterBoiledML) }; } /** * Round a number to a reasonable precision * @param {number} value - The number to round * @param {number} decimals - Number of decimal places * @returns {number} - Rounded number */ roundNumber(value, decimals = 4) { const factor = Math.pow(10, decimals); return Math.round(value * factor) / factor; } /** * Convert results to a string format * @param {FormattedResults} results - Formatted results object * @returns {string} - String representation of results */ stringify(results) { if (this.config.format === 'json') { return JSON.stringify(results, null, 2); } // Support for other formats like CSV could be added here return JSON.stringify(results); } } exports.default = OutputFormatter; //# sourceMappingURL=output-formatter.js.map