23 lines · 1.1 KB
import { createServerFn } from "@tanstack/react-start";
import { z } from "zod";
import { email } from "~/lib/validation";
import { enforceRateLimit, requestIp } from "~/server/limits";
import { requireTurnstile } from "~/server/turnstile";
import { invitedEmail, joinWaitlist, signupsFull } from "~/server/waitlist";

/** Whether the signup form should offer the waitlist instead, and who an invite link was sent to. */
export const getSignupGate = createServerFn({ method: "GET" })
  .validator(z.object({ invite: z.string().max(200).optional() }))
  .handler(async ({ data }) => {
    const invited = data.invite ? await invitedEmail(data.invite) : null;
    return { full: await signupsFull(), invitedEmail: invited, inviteExpired: Boolean(data.invite) && !invited };
  });

export const joinSignupWaitlist = createServerFn({ method: "POST" })
  .validator(z.object({ email, turnstileToken: z.string().max(2048).optional() }))
  .handler(async ({ data }) => {
    await enforceRateLimit("AUTH_LIMITER", `waitlist:${requestIp()}`);
    await requireTurnstile(data.turnstileToken, "signup");
    return { place: await joinWaitlist(data.email.toLowerCase()) };
  });