HomePage
is an async component
Home: what's happened lately, newest first: releases, reviews and advisories (and yanks), or one of them (show);
for a visitor signed in, what people they follow did (following), or what's happened to libraries they use
(mine: in releases they've announced, or in the codebase they gave). Beside it, what to show, and, signed in, the
libraries they use.
import { CODEBASE_COOKIE, everyone, followsOf, libraries, librariesUsed, libraryHref, libraryKey, registryShare, releases, said, shownAttestations, shownRelease, visitor, } from "#codebase/tcmts/registry"; import { AttestationItem, CodebaseForm, FeedItem, Legend, RegistryFrame } from "#codebase/tcmts/registry/pages"; import { cookie } from "#codebase/tcmts/server"; import { at, NavTabs } from "#codebase/tcmts/share"; export async function HomePage({ show }: { show: string }) { registryShare(); const rels = (await releases.find({ state: "mirrored" })).map((r) => r.value); const said_ = await shownAttestations(); const who = await everyone(); const byNamespace = new Map( (await releases.find()) .map((r) => r.value) .filter(shownRelease) .map((r) => [r.namespace, r]), ); const me = await visitor(); const codebase = cookie(CODEBASE_COOKIE) ?? ""; const follows = me && show === "following" ? await followsOf(me.did) : undefined; const mine = me ? await librariesUsed(me.did, codebase || undefined) : undefined; const used = show === "mine" ? mine : undefined; const theirs = (did: string) => !follows || follows.has(did); const about = (namespace: string) => { const r = byNamespace.get(namespace); return !used || (r !== undefined && used.has(libraryKey(r))); }; const mixed = show === "" || show === "following" || show === "mine"; const items = ( (show === "following" || show === "mine") && !me ? [] : [ ...(mixed || show === "releases" ? rels .filter((r) => theirs(r.did) && about(r.namespace)) .map((r) => ({ at: r.createdAt, r })) : []), ...said_ .filter((a) => mixed ? true : show === "reviews" ? a.kind === "review" : show === "advisories" ? a.kind === "advisory" : false, ) .filter((a) => theirs(a.did) && about(a.namespace)) .map((a) => ({ at: a.createdAt, a })), ] ).sort((x, y) => Date.parse(y.at) - Date.parse(x.at)); const count = (k: string) => said_.filter((a) => a.kind === k).length; const filter = (id: string, label: string, n?: number) => ({ id: id || "all", label, href: at(id ? `/?show=${id}` : "/"), ...(n ? { count: n } : {}), }); // (theirs, yanked ones too: it's who uses one that most needs to know) const usedLibs = mine ? (await libraries({ yanked: true })).filter((l) => mine.has(libraryKey(l))) : []; return ( <RegistryFrame tab="activity" title="Activity"> <div className="page cols-feed"> <div className="feedfilters"> <NavTabs label="What to show" vertical selected={show || "all"} tabs={[ filter("", "Everything"), filter("releases", "Releases"), filter("reviews", "Reviews", count("review")), filter("advisories", "Advisories", count("advisory")), ]} /> {me && ( <> <hr /> <NavTabs label="Yours" vertical selected={show} tabs={[filter("following", "People I follow"), filter("mine", "Libraries I use")]} /> <p className="muted"> <small> "People I follow" uses your Bluesky follows; "Libraries I use", your releases and the codebase you give. </small> </p> </> )} </div> <div> {show === "mine" && me && ( <div className="box boxbody"> <div className="muted"> The libraries in releases you've announced{codebase ? ", and in your codebase" : ""} : {used?.size ?? 0}. Give the address of a codebase you serve ( <code>tcm serve</code>) to add the libraries it holds. </div> <CodebaseForm url={codebase} /> </div> )} {items.length ? ( <div className="box feed"> {items .slice(0, 100) .map((x) => "r" in x ? ( <FeedItem key={x.r.uri} r={x.r} who={who.get(x.r.did) ?? { did: x.r.did }} /> ) : ( <AttestationItem key={x.a.uri} a={x.a} who={who.get(x.a.did) ?? { did: x.a.did }} r={byNamespace.get(x.a.namespace)} author={ who.get(byNamespace.get(x.a.namespace)?.did ?? "") ?? (x.a.author ? { did: x.a.author } : undefined) } /> ), )} </div> ) : (show === "following" || show === "mine") && !me ? ( <div className="empty"> Sign in to see what people you follow, and libraries you use, are up to. </div> ) : show === "following" ? ( <div className="empty">Nobody you follow has announced or said anything here yet.</div> ) : show === "mine" ? ( <div className="empty">Nothing has happened to the libraries you use yet.</div> ) : ( <div className="empty"> Nothing announced yet: <code>tcm release --announce</code> announces a release. </div> )} </div> <div className="side"> {me && ( <div className="sect"> <h4>Libraries your codebase uses</h4> {usedLibs.map((l) => { const w = who.get(l.did) ?? { did: l.did }; const advised = said_.some( (a) => a.kind === "advisory" && l.versions.some((v) => v.namespace === a.namespace), ); return ( <div className="row" key={libraryKey(l)}> <a className="mono" href={libraryHref(w, l.package)}> {said(w)}/{l.package} {l.latest.version} </a> {!l.versions.length ? ( <span className="right bad">yanked</span> ) : ( advised && <span className="right bad">advisory</span> )} </div> ); })} {!usedLibs.length && ( <div className="muted"> None the registry knows yet: <a href={at("/?show=mine")}>give your codebase</a>. </div> )} </div> )} <div className="sect"> <h4>Where code runs</h4> <Legend /> </div> </div> </div> </RegistryFrame> ); }
uses
- tcmts.registry.CODEBASE_COOKIE
- tcmts.registry.everyone
- tcmts.registry.followsOf
- tcmts.registry.libraries
- tcmts.registry.librariesUsed
- tcmts.registry.libraryHref
- tcmts.registry.libraryKey
- tcmts.registry.pages.AttestationItem
- tcmts.registry.pages.CodebaseForm
- tcmts.registry.pages.FeedItem
- tcmts.registry.pages.Legend
- tcmts.registry.pages.RegistryFrame
- tcmts.registry.registryShare
- tcmts.registry.releases
- tcmts.registry.said
- tcmts.registry.shownAttestations
- tcmts.registry.shownRelease
- tcmts.registry.visitor
- tcmts.server.cookie
- tcmts.share.NavTabs
- tcmts.share.at