import { randomUUID } from 'crypto'; import prisma from '~/server/utils/prisma'; import { generateVillageForUser } from '~/server/services/villageService'; const ANONYMOUS_COOKIE_NAME = 'smurf-anonymous-session'; /** * Initiates an anonymous user session. * 1. Checks for an existing session cookie. * 2. If found, verifies it corresponds to an existing anonymous user. * 3. If not found or invalid, creates a new anonymous user and a corresponding village. * 4. Sets the session ID in a long-lived cookie. * 5. Returns the session ID and basic user info. */ export default defineEventHandler(async (event) => { const existingSessionId = getCookie(event, ANONYMOUS_COOKIE_NAME); if (existingSessionId) { const user = await prisma.user.findUnique({ where: { anonymousSessionId: existingSessionId, isAnonymous: true }, select: { id: true, anonymousSessionId: true, village: { select: { id: true } } // Include village ID for deletion } }); // If a valid anonymous user is found for this session, reset their progress. if (user) { const villageId = user.village?.id; // Use a transaction to atomically delete all progress. await prisma.$transaction([ // 1. Delete all habits (HabitCompletion records will cascade) prisma.habit.deleteMany({ where: { userId: user.id } }), // 2. Delete all village objects to break the dependency on tiles before deleting the village ...(villageId ? [prisma.villageObject.deleteMany({ where: { villageId } })] : []), // 3. Delete the village if it exists (all related records will cascade) ...(villageId ? [prisma.village.delete({ where: { id: villageId } })] : []), ]); // Re-create the village from scratch. This service will also set initial coins. await generateVillageForUser(user); // Fetch the final, reset state of the user to return const resetUser = await prisma.user.findUnique({ where: { id: user.id }, select: { id: true, anonymousSessionId: true, nickname: true, coins: true, exp: true, isAnonymous: true } }); return resetUser; } } // No valid session found, create a new anonymous user. const newSessionId = randomUUID(); const newUser = await prisma.user.create({ data: { isAnonymous: true, anonymousSessionId: newSessionId, }, select: { id: true, // Also return ID anonymousSessionId: true, nickname: true, coins: true, exp: true, isAnonymous: true // Ensure this flag is returned } }); // Now, generate the village with default tiles for the new anonymous user await generateVillageForUser(newUser); // Set a long-lived cookie (e.g., 1 year) setCookie(event, ANONYMOUS_COOKIE_NAME, newSessionId, { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'lax', maxAge: 365 * 24 * 60 * 60 // 1 year in seconds }); return newUser; });