### Install and Run Aggregator - Bash Source: https://context7.com/fontsource/download-stat-aggregator/llms.txt This bash snippet provides commands to install project dependencies and run the download statistics aggregator locally. It uses 'pnpm' for package management. After execution, the generated output files will be located in the './data/' directory. ```bash # Run the aggregator locally pnpm install pnpm parse # Output files generated in ./data/: ``` -------------------------------- ### Display Dynamic Badges using Shields.io Endpoints - Markdown Source: https://context7.com/fontsource/download-stat-aggregator/llms.txt This markdown snippet demonstrates how to use the generated JSON badge endpoints with Shields.io to create dynamic badges in README files. Each badge URL points to the raw GitHub content of the respective JSON file, allowing Shields.io to fetch and display the latest statistics. ```markdown ![Monthly NPM Downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Ffontsource%2Fdownload-stat-aggregator%2Fmain%2Fdata%2FbadgeMonth.json) ![Total NPM Downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Ffontsource%2Fdownload-stat-aggregator%2Fmain%2Fdata%2FbadgeTotal.json) ![Monthly jsDelivr Downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Ffontsource%2Fdownload-stat-aggregator%2Fmain%2Fdata%2FbadgejsDelivrMonth.json) ![Total jsDelivr Downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Ffontsource%2Fdownload-stat-aggregator%2Fmain%2Fdata%2FbadgejsDelivrTotal.json) ``` -------------------------------- ### HTTP Fetch with Exponential Backoff (JavaScript) Source: https://context7.com/fontsource/download-stat-aggregator/llms.txt Wraps the native fetch API with retry logic using the `p-retry` library. It handles HTTP 429 (rate limit) responses by retrying up to 5 times with a minimum 5-second delay. Dependencies include `p-retry` and the native `fetch` API. ```javascript import pRetry, { AbortError } from "p-retry"; const fetchWithRetry = async (url, pkg) => { return await pRetry( async () => { const response = await fetch(url); if (!response.ok) { if (response.status === 429) { // Rate limited - retry with backoff throw new Error(`429 on ${url}`); } // Other errors - abort immediately throw new AbortError(`Failed to fetch ${url}: ${response.status}`); } return response; }, { onFailedAttempt: ({ error, attemptNumber }) => { if (error.message?.startsWith("429")) { console.log(` ${error.message} ${pkg} — attempt ${attemptNumber} backing off 5s`); } }, retries: 5, minTimeout: 5000, }, ); }; // Example: Fetch NPM downloads for a package const response = await fetchWithRetry( 'https://api.npmjs.org/downloads/point/last-month/@fontsource/roboto', '@fontsource/roboto' ); const data = await response.json(); // Response: { downloads: 3245678, start: "2024-05-01", end: "2024-05-31", package: "@fontsource/roboto" } ``` -------------------------------- ### Fetch Download Statistics for a Single Package (JavaScript) Source: https://context7.com/fontsource/download-stat-aggregator/llms.txt Retrieves monthly and yearly download statistics for a given Fontsource package from both NPM and jsDelivr APIs. It handles rate limiting using `fetchWithRetry` and stores the results in memory. Dependencies include the native `fetch` API and `setTimeout`. ```javascript const statsGet = async (pkg) => { try { // NPM API calls (sequential to avoid rate limits) const npmMonthResp = await fetchWithRetry( `https://api.npmjs.org/downloads/point/last-month/${pkg}`, pkg ); await new Promise((resolve) => setTimeout(resolve, 500)); const npmTotalResp = await fetchWithRetry( `https://api.npmjs.org/downloads/point/last-year/${pkg}`, pkg ); // jsDelivr API calls (parallel for efficiency) const [jsDelivrMonthResp, jsDelivrYearResp, jsDelivrLastYearResp] = await Promise.all([ fetchWithRetry(`https://data.jsdelivr.com/v1/stats/packages/npm/${pkg}?period=month`, pkg), fetchWithRetry(`https://data.jsdelivr.com/v1/stats/packages/npm/${pkg}?period=year`, pkg), fetchWithRetry(`https://data.jsdelivr.com/v1/stats/packages/npm/${pkg}?period=s-year`, pkg), ]); const npmMonthData = await npmMonthResp.json(); const npmTotalData = await npmTotalResp.json(); const jsDelivrMonthData = await jsDelivrMonthResp.json(); const jsDelivrYearData = await jsDelivrYearResp.json(); const jsDelivrLastYearData = await jsDelivrLastYearResp.json(); // Store NPM results lastMonthPopular[pkg] = npmMonthData.downloads; totalPopular[pkg] = npmTotalData.downloads; // Store jsDelivr results (combining two years) jsDelivrLastMonthPopular[pkg] = jsDelivrMonthData.hits.total; jsDelivrTotalPopular[pkg] = jsDelivrYearData.hits.total + jsDelivrLastYearData.hits.total; console.log(`Fetched ${pkg}`); } catch (error) { console.error(`Failed to fetch ${pkg}: ${error.message}`); } }; // Example usage await statsGet('@fontsource/roboto'); await statsGet('@fontsource-variable/inter'); ``` -------------------------------- ### Generate Shields.io Badge JSON - JavaScript Source: https://context7.com/fontsource/download-stat-aggregator/llms.txt This snippet generates JSON files formatted for Shields.io endpoints, enabling dynamic README badges for download counts. It uses the 'millify' library for number formatting and 'json-stringify-pretty-compact' for pretty printing JSON. It calculates and formats monthly and total downloads, and generates popularity rankings. ```javascript import { millify } from "millify"; import stringify from "json-stringify-pretty-compact"; // Calculate totals const downloadsMonth = lastMonthDownloads.reduce((a, b) => a + b, 0); const downloadsTotal = totalDownloads.reduce((a, b) => a + b, 0); // Format with millify (e.g., 31450000 -> "31.45M") const downloadsMonthBadge = millify(downloadsMonth, { precision: 2 }); const downloadsTotalBadge = millify(downloadsTotal, { precision: 2 }); // Generate NPM monthly badge JSON const badgeMonth = { schemaVersion: 1, label: "downloads", message: `${downloadsMonthBadge}/month`, color: "brightgreen" }; fs.writeFileSync("./data/badgeMonth.json", stringify(badgeMonth)); // Output: { "schemaVersion": 1, "label": "downloads", "message": "31.45M/month", "color": "brightgreen" } // Generate jsDelivr badge JSON const badgeJsDelivrMonth = { schemaVersion: 1, label: "jsDelivr", message: `${downloadsJsDelivrMonthBadge}/month`, color: "ff5627" }; fs.writeFileSync("./data/badgejsDelivrMonth.json", stringify(badgeJsDelivrMonth)); // Generate sorted popularity rankings const sortedTotalPopular = Object.fromEntries( Object.entries(totalPopular).sort((a, b) => b[1] - a[1]) ); fs.writeFileSync("./data/totalPopular.json", stringify(sortedTotalPopular)); // Output: { "@fontsource/roboto": 37722010, "@fontsource/inter": 27567514, ... } ``` -------------------------------- ### Orchestrate Production Download Aggregation Pipeline - JavaScript Source: https://context7.com/fontsource/download-stat-aggregator/llms.txt The 'production' function orchestrates the download statistics aggregation. It processes legacy and modern Fontsource packages by fetching data from NPM and Fontsource APIs. Dependencies include 'fs' for file system operations and 'fetchWithRetry' for API requests. It outputs aggregated download counts. ```javascript const production = async () => { // Step 1: Process legacy packages (fontsource-*) using bulk API const legacyFontlist = JSON.parse(fs.readFileSync("./data/legacy-fontlist.json", "utf8")); const legacyIds = Object.keys(legacyFontlist).map((id) => `fontsource-${id}`); console.log(`npm: Fetching ${legacyIds.length} legacy packages via bulk API...`); for (let i = 0; i < legacyIds.length; i += 128) { const batch = legacyIds.slice(i, i + 128); const batchStr = batch.join(","); // NPM bulk API supports comma-separated package names const yearResp = await fetchWithRetry( `https://api.npmjs.org/downloads/point/last-year/${batchStr}`, "" ); const monthResp = await fetchWithRetry( `https://api.npmjs.org/downloads/point/last-month/${batchStr}`, "" ); const yearData = await yearResp.json(); const monthData = await monthResp.json(); // Process each package in batch for (const pkg of batch) { if (yearData[pkg]) totalPopular[pkg] = yearData[pkg].downloads; if (monthData[pkg]) lastMonthPopular[pkg] = monthData[pkg].downloads; } // Also fetch jsDelivr stats in parallel for each package in batch await Promise.all(batch.map((pkg) => fetchJsDelivrStats(pkg))); } // Step 2: Fetch current fontlist from Fontsource API const fontlistResp = await fetch("https://api.fontsource.org/fontlist?variable"); const fontlist = await fontlistResp.json(); // Response: { "roboto": true, "inter": true, "open-sans": false, ... } // Step 3: Process modern packages for (const [key, isVariable] of Object.entries(fontlist)) { await statsGet(`@fontsource/${key}`); if (isVariable) { await statsGet(`@fontsource-variable/${key}`); } } }; // Run the aggregation await production(); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.