128 lines · 4.8 KB
import { createServerFn } from "@tanstack/react-start";
import { z } from "zod";
import { viewerMiddleware, requireViewer } from "./middleware";
import { limitWrite } from "~/server/limits";
import { unauthorized } from "~/server/errors";
import {
  createWebhookIntegration,
  deleteIntegrationById,
  listIntegrationsFor,
  redeliverDelivery,
  sendTestEvent,
  startGithubJob,
  updateIntegrationSettings,
} from "~/server/integrations/manage";
import { INTEGRATION_EVENTS } from "~/lib/integrations";

const scopeRef = z.object({ owner: z.string().min(1).max(100), repo: z.string().min(1).max(100).nullable() });
const integrationEvent = z.enum(INTEGRATION_EVENTS);
const integrationId = z.string().regex(/^[a-z0-9]{20}$/);
const MAX_DIGEST_MINUTES = 7 * 24 * 60;

async function writer<T extends { viewer: Parameters<typeof limitWrite>[0] | null }>(context: T) {
  if (!context.viewer) throw unauthorized("You must be signed in");
  await limitWrite(context.viewer);
  return context.viewer;
}

export const listIntegrations = createServerFn({ method: "GET" })
  .middleware([viewerMiddleware])
  .validator(scopeRef)
  .handler(async ({ data, context }) => listIntegrationsFor(data, context.viewer));

export const createIntegration = createServerFn({ method: "POST" })
  .middleware([viewerMiddleware])
  .validator(
    scopeRef.extend({
      kind: z.enum(["slack", "google_chat", "webhook"]),
      name: z.string().trim().min(1).max(100),
      url: z.string().trim().url().max(2000),
      events: z.array(integrationEvent).max(INTEGRATION_EVENTS.length),