import { mkdirSync, writeFileSync } from "fs"; import { Chart, registerables } from 'chart.js'; import { Canvas } from 'skia-canvas'; // Register all Chart.js controllers Chart.register(...registerables); export function formatPowerShellSummary(summary, platformMetrics) { let platformDownloadTotal = 0; let totalVersions = 0; summary += `| Module | Total Downloads | Latest Version | Version Downloads | Versions | Last Updated |\n`; summary += `| --- | --- | --- | --- | --- | --- |\n`; for (const metric of platformMetrics) { const lastUpdated = metric.metrics?.lastUpdated ? new Date(metric.metrics.lastUpdated).toLocaleDateString() : 'N/A'; const latestVersion = metric.metrics?.latestVersion || 'N/A'; const latestVersionDownloads = metric.metrics?.latestVersionDownloads || 0; const versionCount = metric.metrics?.versionCount || 0; summary += `| ${metric.name} | ${metric.metrics?.downloadsTotal?.toLocaleString() || 0} | ${latestVersion} | ${latestVersionDownloads.toLocaleString()} | ${versionCount} | ${lastUpdated} |\n`; platformDownloadTotal += metric.metrics?.downloadsTotal || 0; totalVersions += versionCount; } summary += `| **Total** | **${platformDownloadTotal.toLocaleString()}** | | | **${totalVersions}** | |\n`; return summary; } export async function addPowerShellDetails(summary, platformMetrics) { summary += `#### PowerShell Module Details:\n\n`; for (const metric of platformMetrics) { summary += `**${metric.name}**:\n`; summary += `- Total Downloads: ${metric.metrics?.downloadsTotal?.toLocaleString() || 0}\n`; summary += `- Latest Version: ${metric.metrics?.latestVersion || 'N/A'}\n`; summary += `- Latest Version Downloads: ${metric.metrics?.latestVersionDownloads?.toLocaleString() || 0}\n`; summary += `- Version Count: ${metric.metrics?.versionCount || 0}\n`; summary += `- Last Updated: ${metric.metrics?.lastUpdated ? new Date(metric.metrics.lastUpdated).toLocaleDateString() : 'N/A'}\n`; summary += `- Package Size: ${metric.metrics?.packageSize ? `${Math.round(metric.metrics.packageSize / 1024)} KB` : 'N/A'}\n`; summary += `\n`; } summary += `\n\n`; const chartOutputPath = './charts/powershell'; mkdirSync(chartOutputPath, { recursive: true }); const svgOutputPathList = await createPowerShellCharts(platformMetrics, chartOutputPath); for (const svgOutputPath of svgOutputPathList) { summary += `![${svgOutputPath}](${svgOutputPath})\n`; } return summary; } export async function createPowerShellCharts(platformMetrics, outputPath) { const svgOutputPathList = []; // Only create charts if there's download data const metricsWithData = platformMetrics.filter(metric => metric.metrics?.downloadsRange && metric.metrics.downloadsRange.length > 0); if (metricsWithData.length > 0) { const svgOutputPath = await createCombinedDownloadsChart(metricsWithData, outputPath); svgOutputPathList.push(svgOutputPath); const svgOutputPathCumulative = await createCombinedCumulativeDownloadsChart(metricsWithData, outputPath); svgOutputPathList.push(svgOutputPathCumulative); } return svgOutputPathList; } // Color palette for different modules const colors = [ 'rgba(54, 162, 235, 0.8)', 'rgba(255, 99, 132, 0.8)', 'rgba(75, 192, 192, 0.8)', 'rgba(255, 205, 86, 0.8)', 'rgba(153, 102, 255, 0.8)', 'rgba(255, 159, 64, 0.8)', 'rgba(199, 199, 199, 0.8)', 'rgba(83, 102, 255, 0.8)', 'rgba(255, 99, 132, 0.8)', 'rgba(54, 162, 235, 0.8)' ]; const borderColors = [ 'rgba(54, 162, 235, 1)', 'rgba(255, 99, 132, 1)', 'rgba(75, 192, 192, 1)', 'rgba(255, 205, 86, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)', 'rgba(199, 199, 199, 1)', 'rgba(83, 102, 255, 1)', 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)' ]; export async function createCombinedDownloadsChart(metrics, outputPath) { const svgOutputPath = `${outputPath}/powershell-combined-downloads.svg`; // Get all unique dates across all modules for the x-axis const allDates = new Set(); for (const metric of metrics) { const downloadsRange = metric.metrics?.downloadsRange || []; for (const download of downloadsRange) { allDates.add(download.day); } } // Sort all dates chronologically const sortedAllDates = Array.from(allDates).sort((a, b) => new Date(a).getTime() - new Date(b).getTime()); // Create datasets for each module (one line per module) const data = []; for (const metric of metrics) { const downloadsRange = metric.metrics?.downloadsRange || []; for (const date of sortedAllDates) { const downloads = downloadsRange.filter(d => d.day === date).reduce((sum, d) => sum + d.downloads, 0); data.push(downloads); } } const labels = sortedAllDates.map(date => new Date(date).toLocaleDateString('en-US', { month: 'short', year: '2-digit', day: 'numeric' })); const canvas = new Canvas(1200, 800); const chart = new Chart(canvas, { type: 'line', data: { labels: labels, datasets: [{ data, backgroundColor: 'rgba(54, 162, 235, 0.2)', borderColor: 'rgba(54, 162, 235, 1)', borderWidth: 3, fill: true, tension: 0.1 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'PowerShell Modules - Downloads Over Time', font: { size: 16 } }, legend: { display: true } }, scales: { x: { title: { display: true, text: 'Release Date' } }, y: { type: 'linear', title: { display: true, text: 'Downloads' }, beginAtZero: true, ticks: { stepSize: 1000 } } } } }); const svgBuffer = await canvas.toBuffer('svg', { matte: 'white' }); writeFileSync(svgOutputPath, svgBuffer); chart.destroy(); return svgOutputPath; } export async function createCombinedCumulativeDownloadsChart(metrics, outputPath) { const svgOutputPath = `${outputPath}/powershell-cumulative-downloads.svg`; // Get all unique dates across all modules for the x-axis const allDates = new Set(); for (const metric of metrics) { const downloadsRange = metric.metrics?.downloadsRange || []; for (const download of downloadsRange) { allDates.add(download.day); } } // Sort all dates chronologically const sortedAllDates = Array.from(allDates).sort((a, b) => new Date(a).getTime() - new Date(b).getTime()); const labels = sortedAllDates.map(date => new Date(date).toLocaleDateString('en-US', { month: 'short', year: '2-digit', day: 'numeric' })); const data = []; let runningTotal = 0; for (const date of sortedAllDates) { const downloads = metrics.reduce((sum, metric) => sum + (metric.metrics?.downloadsRange?.find(d => d.day === date)?.downloads || 0), 0); runningTotal += downloads; data.push(runningTotal); } const canvas = new Canvas(1200, 800); const chart = new Chart(canvas, { type: 'line', data: { labels: labels, datasets: [{ label: 'Cumulative Downloads', data, backgroundColor: 'rgba(54, 162, 235, 0.2)', borderColor: 'rgba(54, 162, 235, 1)', borderWidth: 3, fill: true, tension: 0.1 }] }, options: { responsive: true, plugins: { title: { display: true, text: 'PowerShell Modules - Cumulative Downloads', font: { size: 16 } }, legend: { display: true } }, scales: { x: { title: { display: true, text: 'Release Date' } }, y: { title: { display: true, text: 'Cumulative Downloads' }, beginAtZero: true, ticks: { stepSize: 5000 } } } } }); const svgBuffer = await canvas.toBuffer('svg', { matte: 'white' }); writeFileSync(svgOutputPath, svgBuffer); chart.destroy(); return svgOutputPath; }