97 lines
3.0 KiB
TypeScript
97 lines
3.0 KiB
TypeScript
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;
|
|
});
|