import type { Hono } from "hono"; import { html } from "../pages/html.ts"; import { plural } from "../pages/layout.ts"; import { downloadsByDay, repoDownloads, topFiles, utcDay } from "../releases/releases.ts"; import { type AdminContext, adminPage } from "./console.ts"; import { allRepos } from "./store.ts"; const DAYS_SHOWN = 30; const TOP_FILES = 10; const DAY_MS = 24 * 60 * 60 * 1000; /** §24's Downloads section: the last 30 days, each repo's totals and the top files. */ export function registerDownloads(app: Hono, ctx: AdminContext): void { app.get("/admin/downloads", (c) => { // An unknown repo narrows nothing, as the issues list treats one. const repos = allRepos(ctx.kepr).map((repo) => repo.name); const repo = repos.find((name) => name === c.req.query("repo")) ?? ""; const now = Date.now(); const days = Array.from({ length: DAYS_SHOWN }, (_, i) => utcDay(now - (DAYS_SHOWN - 1 - i) * DAY_MS), ); const since = days[0] as string; const counts = downloadsByDay(ctx.kepr, since, repo); const peak = Math.max(1, ...counts.values()); const option = (name: string) => html``; const body = html`

last ${String(DAYS_SHOWN)} days

    ${days.map((day) => { const n = counts.get(day) ?? 0; return html`
  1. ${day} ${String(n)}
  2. `; })}

repositories

${repoDownloads(ctx.kepr, since).map( (row) => html`

${row.repo} ${plural(row.total, "download")} · ${String(row.recent)} in ${String(DAYS_SHOWN)} days

`, )}

most downloaded files

${topFiles(ctx.kepr, TOP_FILES).map( ( row, ) => html`

${row.repo} ${row.version} ${row.platform} ${plural(row.count, "download")}

`, )}
`; return c.html(adminPage(c, ctx, "downloads", body)); }); }