diff --git a/apps/web/src/app/api/waitlist/route.ts b/apps/web/src/app/api/waitlist/route.ts index e949ea6..f0b1c1f 100644 --- a/apps/web/src/app/api/waitlist/route.ts +++ b/apps/web/src/app/api/waitlist/route.ts @@ -4,6 +4,11 @@ import { waitlist } from "@/lib/db/schema"; import { eq } from "drizzle-orm"; import { nanoid } from "nanoid"; import { waitlistRateLimit } from "@/lib/rate-limit"; +import { z } from "zod"; + +const waitlistSchema = z.object({ + email: z.string().email("Invalid email format").min(1, "Email is required"), +}); export async function POST(request: NextRequest) { // Rate limit check @@ -18,20 +23,8 @@ export async function POST(request: NextRequest) { } try { - const { email } = await request.json(); - - if (!email || typeof email !== "string") { - return NextResponse.json({ error: "Email is required" }, { status: 400 }); - } - - // Validate email format - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - if (!emailRegex.test(email)) { - return NextResponse.json( - { error: "Invalid email format" }, - { status: 400 } - ); - } + const body = await request.json(); + const { email } = waitlistSchema.parse(body); // Check if email already exists const existingEmail = await db @@ -58,6 +51,11 @@ export async function POST(request: NextRequest) { { status: 201 } ); } catch (error) { + if (error instanceof z.ZodError) { + const firstError = error.errors[0]; + return NextResponse.json({ error: firstError.message }, { status: 400 }); + } + console.error("Waitlist signup error:", error); return NextResponse.json( { error: "Internal server error" },