Files
Epicure/apps/web/app/api/v1/push/subscribe/route.ts
T
2026-07-01 11:10:37 +02:00

72 lines
1.8 KiB
TypeScript

import { NextResponse } from "next/server";
import { z } from "zod";
import { db, pushSubscriptions, eq, and } from "@epicure/db";
import { requireSession } from "@/lib/api-auth";
const subscribeSchema = z.object({
endpoint: z.string().url(),
keys: z.object({
p256dh: z.string(),
auth: z.string(),
}),
});
const unsubscribeSchema = z.object({
endpoint: z.string(),
});
export async function POST(request: Request) {
const { session, response } = await requireSession();
if (response) return response;
const json = await request.json();
const parsed = subscribeSchema.safeParse(json);
if (!parsed.success) {
return NextResponse.json({ error: "Invalid body" }, { status: 400 });
}
const body = parsed.data;
await db
.insert(pushSubscriptions)
.values({
id: crypto.randomUUID(),
userId: session!.user.id,
endpoint: body.endpoint,
p256dh: body.keys.p256dh,
auth: body.keys.auth,
})
.onConflictDoUpdate({
target: pushSubscriptions.endpoint,
set: {
p256dh: body.keys.p256dh,
auth: body.keys.auth,
},
setWhere: eq(pushSubscriptions.userId, session!.user.id),
});
return NextResponse.json({ ok: true });
}
export async function DELETE(request: Request) {
const { session, response } = await requireSession();
if (response) return response;
const json = await request.json();
const parsed = unsubscribeSchema.safeParse(json);
if (!parsed.success) {
return NextResponse.json({ error: "Invalid body" }, { status: 400 });
}
await db
.delete(pushSubscriptions)
.where(
and(
eq(pushSubscriptions.endpoint, parsed.data.endpoint),
eq(pushSubscriptions.userId, session!.user.id)
)
);
return NextResponse.json({ ok: true });
}