From 2147d03a984d81028d082bac0797028c8ebe392c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CSebastian?= <64795732+slegarraga@users.noreply.github.com> Date: Thu, 18 Jun 2026 11:13:44 -0400 Subject: [PATCH] chore: use direct npm download badges --- .github/workflows/download-badge.yml | 31 ------ README.md | 2 +- badges/npm-downloads/llm-errors.json | 8 -- package.json | 4 +- scripts/update-download-badge.mjs | 159 --------------------------- 5 files changed, 2 insertions(+), 202 deletions(-) delete mode 100644 .github/workflows/download-badge.yml delete mode 100644 badges/npm-downloads/llm-errors.json delete mode 100644 scripts/update-download-badge.mjs diff --git a/.github/workflows/download-badge.yml b/.github/workflows/download-badge.yml deleted file mode 100644 index 7f9f23b..0000000 --- a/.github/workflows/download-badge.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Download badge - -on: - schedule: - - cron: '42 11 * * *' - workflow_dispatch: - -permissions: - contents: write - -jobs: - refresh: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 - with: - node-version: 22 - - run: npm run badges:downloads - - name: Commit badge update - run: | - if git diff --quiet -- badges/npm-downloads; then - echo "Download badge is already current." - exit 0 - fi - - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add badges/npm-downloads - git commit -m "chore: refresh npm download badge" - git push diff --git a/README.md b/README.md index f5488bd..1e1c784 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # llm-errors [![npm version](https://img.shields.io/npm/v/llm-errors.svg)](https://www.npmjs.com/package/llm-errors) -[![npm downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fslegarraga%2Fllm-errors%2Fmain%2Fbadges%2Fnpm-downloads%2Fllm-errors.json)](https://www.npmjs.com/package/llm-errors) +[![npm downloads](https://img.shields.io/npm/dm/llm-errors.svg)](https://www.npmjs.com/package/llm-errors) [![CI](https://github.com/slegarraga/llm-errors/actions/workflows/ci.yml/badge.svg)](https://github.com/slegarraga/llm-errors/actions/workflows/ci.yml) [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/slegarraga/llm-errors/badge)](https://scorecard.dev/viewer/?uri=github.com/slegarraga/llm-errors) [![license](https://img.shields.io/npm/l/llm-errors.svg)](./LICENSE) diff --git a/badges/npm-downloads/llm-errors.json b/badges/npm-downloads/llm-errors.json deleted file mode 100644 index f6ba595..0000000 --- a/badges/npm-downloads/llm-errors.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "schemaVersion": 1, - "label": "downloads", - "message": "492/30d", - "color": "green", - "cacheSeconds": 3600, - "namedLogo": "npm" -} diff --git a/package.json b/package.json index 5bdd21f..bad72ca 100644 --- a/package.json +++ b/package.json @@ -64,9 +64,7 @@ "format": "prettier --write .", "format:check": "prettier --check .", "prepublishOnly": "npm run build", - "prepare": "npm run build", - "badges:downloads": "node scripts/update-download-badge.mjs", - "badges:downloads:check": "node scripts/update-download-badge.mjs --check" + "prepare": "npm run build" }, "devDependencies": { "@eslint/js": "^10.0.1", diff --git a/scripts/update-download-badge.mjs b/scripts/update-download-badge.mjs deleted file mode 100644 index d114274..0000000 --- a/scripts/update-download-badge.mjs +++ /dev/null @@ -1,159 +0,0 @@ -import https from 'node:https'; -import { mkdir, readFile, writeFile } from 'node:fs/promises'; -import path from 'node:path'; - -const pkg = JSON.parse(await readFile('package.json', 'utf8')).name; -const outDir = path.join('badges', 'npm-downloads'); -const args = new Set(process.argv.slice(2)); -const checkOnly = args.has('--check'); - -function isoDate(date) { - return date.toISOString().slice(0, 10); -} - -function defaultWindow() { - const now = process.env.DOWNLOAD_BADGE_TODAY - ? new Date(`${process.env.DOWNLOAD_BADGE_TODAY}T00:00:00.000Z`) - : new Date(); - - if (Number.isNaN(now.getTime())) { - throw new Error( - `Invalid DOWNLOAD_BADGE_TODAY: ${process.env.DOWNLOAD_BADGE_TODAY}`, - ); - } - - const end = new Date( - Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() - 1), - ); - const start = new Date(end); - start.setUTCDate(start.getUTCDate() - 29); - - return { - start: process.env.DOWNLOAD_BADGE_START || isoDate(start), - end: process.env.DOWNLOAD_BADGE_END || isoDate(end), - }; -} - -function getJson(url) { - return new Promise((resolve, reject) => { - const request = https.get( - url, - { - headers: { - accept: 'application/json', - 'user-agent': 'npm-package-download-badge-refresh', - }, - }, - (response) => { - let body = ''; - response.setEncoding('utf8'); - response.on('data', (chunk) => { - body += chunk; - }); - response.on('end', () => { - if ( - (response.statusCode || 0) < 200 || - (response.statusCode || 0) >= 300 - ) { - reject( - new Error( - `Request failed: ${response.statusCode} ${response.statusMessage}`, - ), - ); - return; - } - - try { - resolve(JSON.parse(body)); - } catch (error) { - reject(error); - } - }); - }, - ); - - request.on('error', reject); - request.setTimeout(15000, () => { - request.destroy(new Error('Request timed out')); - }); - }); -} - -function formatDownloads(downloads) { - if (downloads >= 1_000_000) { - return `${(downloads / 1_000_000).toFixed(1).replace(/\.0$/, '')}m`; - } - - if (downloads >= 1_000) { - return `${(downloads / 1_000).toFixed(1).replace(/\.0$/, '')}k`; - } - - return String(downloads); -} - -function colorFor(downloads) { - if (downloads === 0) return 'red'; - if (downloads < 100) return 'yellowgreen'; - if (downloads < 1_000) return 'green'; - return 'brightgreen'; -} - -async function fetchDownloads(start, end) { - const url = `https://api.npmjs.org/downloads/range/${start}:${end}/${encodeURIComponent(pkg)}`; - const body = await getJson(url); - const rows = Array.isArray(body.downloads) ? body.downloads : []; - const downloads = rows.reduce( - (sum, row) => sum + Number(row.downloads || 0), - 0, - ); - - return { downloads, start: body.start || start, end: body.end || end }; -} - -function badgeJson(result) { - return { - schemaVersion: 1, - label: 'downloads', - message: `${formatDownloads(result.downloads)}/30d`, - color: colorFor(result.downloads), - cacheSeconds: 3600, - namedLogo: 'npm', - }; -} - -async function readExisting(file) { - try { - return await readFile(file, 'utf8'); - } catch (error) { - if (error?.code === 'ENOENT') return null; - throw error; - } -} - -async function main() { - const { start, end } = defaultWindow(); - const result = await fetchDownloads(start, end); - const file = path.join(outDir, `${pkg}.json`); - const next = `${JSON.stringify(badgeJson(result), null, 2)}\n`; - const current = await readExisting(file); - - if (checkOnly && current !== next) { - throw new Error( - `${file} is stale. Run node scripts/update-download-badge.mjs`, - ); - } - - if (!checkOnly) { - await mkdir(outDir, { recursive: true }); - await writeFile(file, next); - } - - console.log( - `${pkg}: ${result.downloads} downloads (${result.start}..${result.end})`, - ); -} - -main().catch((error) => { - console.error(error instanceof Error ? error.message : error); - process.exit(1); -});