import { createServerFn } from "@tanstack/react-start"; import { z } from "zod"; import { requireViewer, viewerMiddleware } from "./middleware"; import { limitWrite } from "~/server/limits"; import { notFoundError } from "~/server/errors"; import { requireOwnerAdmin } from "~/server/ci/config-admin"; import { publicUrl } from "~/server/events/emit"; import { mintRegistrationToken } from "~/server/ci/runner-registration"; import { listOwnerRunners, removeOwnerRunner } from "~/server/ci/runner-owner"; const ownerRef = z.object({ owner: z.string().min(1).max(64) }); export const listOwnerRunnersFn = createServerFn({ method: "GET" }) .middleware([viewerMiddleware]) .validator(ownerRef) .handler(async ({ data, context }) => { const account = await requireOwnerAdmin(data.owner, requireViewer(context.viewer)); return { owner: account.name, runners: await listOwnerRunners(account.id), serverUrl: publicUrl("/").replace(/\/$/, ""), }; }); export const createOwnerRunnerRegistration = createServerFn({ method: "POST" }) .middleware([viewerMiddleware]) .validator( ownerRef.extend({ labels: z.array(z.string().trim().min(1).max(32)).max(20), isolation: z.enum(["container", "none"]), }), ) .handler(async ({ data, context }) => { const viewer = requireViewer(context.viewer); await limitWrite(viewer); const account = await requireOwnerAdmin(data.owner, viewer); return mintRegistrationToken({ kind: "owner", ownerId: account.id }, viewer.id, data.labels, data.isolation); }); export const deleteOwnerRunner = createServerFn({ method: "POST" }) .middleware([viewerMiddleware]) .validator(ownerRef.extend({ id: z.string().min(1).max(64) })) .handler(async ({ data, context }) => { const viewer = requireViewer(context.viewer); await limitWrite(viewer); const account = await requireOwnerAdmin(data.owner, viewer); if (!(await removeOwnerRunner(account.id, data.id))) throw notFoundError("Runner not found"); return { ok: true }; });