import { createServerFn } from "@tanstack/react-start";
import { isTakenDown } from "~/lib/account-disable";
import { z } from "zod";
import { viewerMiddleware } from "./middleware";
import { first } from "~/server/db";
import { repoDb } from "~/server/scoped-db";
import { limitBrowse } from "~/server/limits";
import { loadRepo, repoPermission } from "~/server/repos";
import { withStore } from "~/server/git/store";
import { accountName } from "~/lib/validation";
const ISSUE_REF = /^([^/]+)\/([^#]+)#(\d+)$/;
const COMMIT_REF = /^([^/]+)\/([^@]+)@([0-9a-f]{7,40})$/;
const FULL_SHA = 40;
const SHORT_SHA = 7;
const MAX_TEXT = 200;
async function readableRepo(owner: string, name: string, viewer: Parameters<typeof repoPermission>[1]) {
const repo = await loadRepo(owner, name);
if (!repo || (await repoPermission(repo, viewer)) === "none") return null;
return repo;
}
/** Preview data for `data-hovercard` links rendered by the markdown pipeline. */
export const getHovercard = createServerFn({ method: "GET" })
.middleware([viewerMiddleware])
.validator(z.object({ kind: z.enum(["issue", "user", "team", "commit"]), ref: z.string().min(1).max(300) }))
.handler(async ({ data, context }) => {
await limitBrowse(context.viewer);
if (data.kind === "user" || data.kind === "team") {
const name = accountName.safeParse(data.ref.split("/")[0]);
if (!name.success) return null;
const account = await first<{
id: string;
name: string;
display_name: string | null;
bio: string | null;
kind: string;
website: string | null;
avatar_key: string | null;