/** * POST /api/users/me/push-token * * Client (Expo) ruft das nach `getExpoPushTokenAsync()` auf, um seinen Token * im Backend zu hinterlegen. Idempotent: bei existierendem Token wird nur * lastUsedAt + enabled aktualisiert. * * Body: { token: string, platform: "ios" | "android", deviceId?: string } */ import { requireUser } from "../../../utils/auth"; import { usePrisma } from "../../../utils/prisma"; import { z } from "zod"; const Body = z.object({ token: z.string().min(10).max(200), // ExponentPushToken[xxx] platform: z.enum(["ios", "android"]), deviceId: z.string().max(120).optional(), }); export default defineEventHandler(async (event) => { const user = await requireUser(event); const raw = await readBody(event).catch(() => ({})); const parsed = Body.safeParse(raw); if (!parsed.success) { throw createError({ statusCode: 400, data: { error: "INVALID_BODY", detail: parsed.error.flatten() }, }); } const { token, platform, deviceId } = parsed.data; const db = usePrisma(); await db.pushToken.upsert({ where: { token }, create: { userId: user.id, token, platform, deviceId: deviceId ?? null, enabled: true, lastUsedAt: new Date(), }, update: { userId: user.id, // Token könnte das Device gewechselt haben platform, deviceId: deviceId ?? null, enabled: true, lastUsedAt: new Date(), }, }); return { success: true, data: { ok: true } }; });