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.

g1t.sh
36 linesCodeBlameRaw
1import { data } from "react-router";
2
3import type { Route } from "./+types/ref";
4import { work } from "../../../lib/services.server";
5import { requireUser, roleIn } from "../../../lib/session.server";
6
7/** What a reference chip's card shows (components/chat/ref-chip.tsx): an issue or pull request, as the viewer may see it. */
8export type RefCard = { kind: "issue" | "pull"; repo: string; number: number; title: string; state: string };
9
10/**
11 * `-/chat/ref?repo=<namespace>/<name>&number=<n>`: the card that opens over
12 * an `owner/repo#12` chip in chat and in g1t's answers. Issues and pull
13 * requests share numbers: the issue if there is one, else the pull
14 * request. Only what the viewer may read; anything else is not found.
15 * Kept a minute by the browser.
16 */
17export async function loader({ params, context, request }: Route.LoaderArgs) {
18 const viewer = requireUser(context, request);
19 if (!roleIn(viewer, params.owner)) throw data(null, { status: 404 });
20 const url = new URL(request.url);
21 const [namespace, name] = (url.searchParams.get("repo") ?? "").split("/");
22 const number = Number(url.searchParams.get("number"));
23 const headers = { "cache-control": "private, max-age=60", vary: "Cookie" };
24 if (!namespace || !name || !Number.isInteger(number) || number < 1) return Response.json({ error: "not_found" }, { status: 404, headers });
25 const repo = { namespace: namespace.toLowerCase(), name };
26 const issue = await work.getIssue(repo, number, viewer).catch(() => null);
27 let card: RefCard | null = issue?.ok
28 ? { kind: "issue", repo: `${repo.namespace}/${repo.name}`, number, title: issue.value.issue.title, state: String(issue.value.issue.state) }
29 : null;
30 if (!card) {
31 const pull = await work.getPull(repo, number, viewer).catch(() => null);
32 if (pull?.ok) card = { kind: "pull", repo: `${repo.namespace}/${repo.name}`, number, title: pull.value.pull.title, state: pull.value.pull.status };
33 }
34 if (!card) return Response.json({ error: "not_found" }, { status: 404, headers });
35 return Response.json(card, { headers });
36}