1import { newestSaves, type RepoStats, repoStats, type Save } from "../mirror/queries.ts";2import { publicRepoNames } from "../server/db.ts";3import { type Html, html } from "./html.ts";4import { openPublicRepo, type PageContext, type PublicRepo, plural } from "./layout.ts";5import { repoIntro } from "./repo.ts";678export type LibraryRepo = PublicRepo & { stats: RepoStats; description: string };910export type RecentSave = { repo: string; save: Save };111213export function publicLibrary(ctx: PageContext): LibraryRepo[] {14 return publicRepoNames(ctx.kepr).flatMap((name) => {15 const repo = openPublicRepo(ctx, name);16 if (!repo) return [];17 const description = repoIntro(repo)?.text ?? "";18 return [{ ...repo, stats: repoStats(repo.mirror), description }];19 });20}212223export function recentSaves(library: LibraryRepo[], limit: number): RecentSave[] {24 return library25 .flatMap((repo) =>26 newestSaves(repo.mirror, limit).map((save) => ({ repo: repo.settings.name, save })),27 )28 .sort((a, b) => b.save.created_at - a.save.created_at)29 .slice(0, limit);30}3132export function repoCards(library: LibraryRepo[]): Html {33 return html`<div class="card-grid">${library.map(repoCard)}</div>`;34}353637function repoCard(repo: LibraryRepo): Html {38 const { name, category } = repo.settings;39 return html`<a class="repo-card" href="/${name}">40<div class="repo-card-head"><span class="repo-card-name">${41 name42 }</span><span class="repo-card-saves mono">${plural(repo.stats.saves, "save")}</span></div>43${repo.description && html`<p class="repo-card-desc">${repo.description}</p>`}44${category && html`<p class="repo-card-cat">${category}</p>`}45</a>`;46}