Skip to content
32 linesCodeBlameRaw
1/**
2 * The card over a person's name or avatar, fetched when it first opens
3 * (components/user-card.tsx): their public profile, the workspaces the
4 * viewer may know they belong to, and, given `?repo=owner/name` the viewer
5 * can read, how recently they committed there. Works signed out, with
6 * public answers only. Kept a minute by the browser, for this viewer only.
7 */
8import type { Route } from "./+types/hovercard-user";
9import { buildCard, parseRepo } from "../lib/hovercard";
10import { identity, repos } from "../lib/services.server";
11import { getViewer } from "../lib/session.server";
12
13export async function loader({ params, request, context }: Route.LoaderArgs) {
14 const viewer = getViewer(context);
15 const repo = parseRepo(new URL(request.url).searchParams.get("repo"));
16 const card = await buildCard(
17 params.username,
18 viewer,
19 repo,
20 {
21 profile: (username) => identity.profile(username),
22 accountId: async (username) => (await identity.userByUsername(username))?.id ?? null,
23 publicNamespaces: (id) => repos.publicNamespaces(id),
24 profileWorkspaces: (username, who, publicIn) => identity.profileWorkspaces(username, who, publicIn),
25 contributors: (path, who) => repos.contributors(path, who),
26 },
27 Date.now(),
28 );
29 const headers = { "cache-control": "private, max-age=60", vary: "Cookie" };
30 if (!card) return Response.json({ error: "not_found" }, { status: 404, headers });
31 return Response.json(card, { headers });
32}