| 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 | */ |
| 10 | import type { Route } from "./+types/blame-data"; |
| 11 | import { showCommits } from "../../lib/commit-people.server"; |
| 12 | import { repos } from "../../lib/services.server"; |
| 13 | import { getViewer } from "../../lib/session.server"; |
| 14 | |
| 15 | const HEADERS = { |
| 16 | "cache-control": "private, no-store", |
| 17 | "x-robots-tag": "noindex, nofollow", |
| 18 | }; |
| 19 | |
| 20 | export 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 | } |