Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

32 linesCodeBlameRaw
1/**
2 * A file's blame at a ref, as JSON, for the blame view to fetch once the
3 * file is on screen: `/<owner>/<repo>/blame/<ref>/<path>`. A first blame
4 * walks the file's history in repos and can take longer than the page's
5 * stream may stay open (entry.server.tsx `streamTimeout`), so it is asked
6 * for on its own request instead; once worked out, repos keeps it and it
7 * comes back at once. Kept out of indexes like the blame view
8 * (lib/robots.ts).
9 */
10import type { Route } from "./+types/blame-data";
11import { showCommits } from "../../lib/commit-people.server";
12import { repos } from "../../lib/services.server";
13import { getViewer } from "../../lib/session.server";
14
15const HEADERS = {
16 "cache-control": "private, no-store",
17 "x-robots-tag": "noindex, nofollow",
18};
19
20export async function loader({ params, context }: Route.LoaderArgs) {
21 const viewer = getViewer(context);
22 const path = { namespace: params.owner, name: params.repo };
23 const file = params["*"] ?? "";
24 const found = await repos.blame(path, viewer, params.ref, file).catch(() => null);
25 if (!found?.ok) {
26 const status = found?.error.code === "not_found" ? 404 : 502;
27 return Response.json({ blame: null }, { status, headers: HEADERS });
28 }
29 // Every commit's people at once.
30 const blame = { ...found.value, commits: await showCommits(found.value.commits) };
31 return Response.json({ blame }, { headers: HEADERS });
32}