import { createServerFn } from "@tanstack/react-start";
import { assertBelowCap, CAPS } from "~/server/limits";
import { z } from "zod";
import { requireViewer, viewerMiddleware } from "./middleware";
import { all, batch, first, placeholders, run, stmt } from "~/server/db";
import { randomId } from "~/server/crypto";
import { requireRepoAccess } from "~/server/repos";
import { loadIssue, applyLabels, issueUrl } from "~/server/issues";
import { addIssueEvent } from "~/server/pulls";
import { emitNotification } from "~/server/events/emit";
import { notFoundError } from "~/server/errors";
import { labelColor, repoRef } from "~/lib/validation";
import type { LabelInfo } from "./issues";
export const setIssueLabels = createServerFn({ method: "POST" })
.middleware([viewerMiddleware])
.validator(repoRef.extend({ number: z.number().int(), labels: z.array(z.string()).max(50) }))
.handler(async ({ data, context }) => {
const viewer = requireViewer(context.viewer);
const access = await requireRepoAccess(data.owner, data.repo, viewer, "write");
const issue = await loadIssue(access.repo.id, data.number);
if (!issue) throw notFoundError("Issue not found");
await applyLabels(access.repo.id, issue.id, data.labels);
await addIssueEvent(issue.id, viewer.id, "labeled", { labels: data.labels });
return { ok: true };
});
export const setIssueAssignees = createServerFn({ method: "POST" })
.middleware([viewerMiddleware])
.validator(repoRef.extend({ number: z.number().int(), usernames: z.array(z.string()).max(10) }))
.handler(async ({ data, context }) => {
const viewer = requireViewer(context.viewer);
const access = await requireRepoAccess(data.owner, data.repo, viewer, "write");
const issue = await loadIssue(access.repo.id, data.number);
if (!issue) throw notFoundError("Issue not found");
const users = data.usernames.length
? await all<{ id: string }>(
`SELECT a.id FROM accounts a JOIN users u ON u.account_id = a.id WHERE a.name IN (${placeholders(data.usernames.length)})`,
...data.usernames,
)