1import type { Hono } from "hono";2import { fileAt, headId, history, type Save, saveByPrefix } from "../mirror/queries.ts";3import { type Html, html } from "./html.ts";4import {5 cacheFor,6 notFound,7 openPublicRepo,8 type PageContext,9 type PublicRepo,10 page,11 relativeTime,12} from "./layout.ts";1314const RECENT = 20;1516export function registerArchivesPage(app: Hono, ctx: PageContext): void {17 app.get("/:repo/archives", (c) => {18 const repo = openPublicRepo(ctx, c.req.param("repo"));19 if (!repo) return notFound(c, ctx);20 const name = repo.settings.name;21 const id = headId(repo.mirror);22 const head = id ? saveByPrefix(repo.mirror, id) : null;23 const recent = history(repo.mirror, RECENT + 1, 0).filter((save) => save.id !== head?.id);24 cacheFor(c, false);25 return c.html(26 page(ctx, {27 title: `archives · ${name}`,28 description: `Source tarballs of ${name}, one per save.`,29 path: `/${name}/archives`,30 body: html`<p class="breadcrumb mono"><a href="/${name}">${name}</a></p>31<h1 class="file-page-title">archives</h1>32<section class="repo-section">33${head ? [row(ctx, repo, head, true), ...recent.slice(0, RECENT).map((save) => row(ctx, repo, save, false))] : html`<p class="muted mono save-empty">no saves yet</p>`}34</section>`,35 }),36 );37 });38}39404142function row(ctx: PageContext, repo: PublicRepo, save: Save, isHead: boolean): Html {43 const name = repo.settings.name;44 const file = isHead ? "HEAD" : save.id;45 const tarball = `/${name}/archive/${file}.tar.gz`;46 const nix = `nix profile add https://${ctx.domain}${tarball}`;47 const hasFlake = fileAt(repo.mirror, save.id, "flake.nix") !== null;48 49 const id = save.is_checkpoint50 ? html`<span class="history-id">${save.id}</span>`51 : html`<a class="history-id" href="/${name}/saves/${save.id}">${save.id}</a>`;52 return html`<div class="archive-row">53<p class="archive-save">${isHead && html`<span class="archive-head mono">HEAD</span>`}${id}<span class="history-msg archive-msg">${save.message.split("\n")[0]}</span><span class="history-when">${relativeTime(save.created_at)}</span></p>54<p class="archive-links mono"><a href="${tarball}">↓ ${name}-${isHead ? "HEAD" : save.id.slice(0, 8)}.tar.gz</a></p>55${hasFlake && html`<div class="install-line"><code>${nix}</code><button type="button" class="copy-btn" data-copy="${nix}" hidden>copy</button></div>`}56</div>`;57}