pstream-backend/server/routes/users/[id]/lists/index.post.ts
2026-03-01 20:34:34 +05:30

96 lines
2.6 KiB
TypeScript

import { useAuth } from '#imports';
import { prisma } from '~/utils/prisma';
import { z } from 'zod';
import { uuidv7 } from 'uuidv7';
const listItemSchema = z.object({
tmdb_id: z.string(),
type: z.enum(['movie', 'tv']),
});
const createListSchema = z.object({
name: z.string().min(1).max(255),
description: z.string().max(255).optional().nullable(),
items: z.array(listItemSchema).optional(),
public: z.boolean().optional(),
});
export default defineEventHandler(async event => {
const userId = event.context.params?.id;
const session = await useAuth().getCurrentSession();
if (session.user !== userId) {
throw createError({
statusCode: 403,
message: 'Cannot modify user other than yourself',
});
}
const body = await readBody(event);
let parsedBody;
try {
parsedBody = typeof body === 'string' ? JSON.parse(body) : body;
} catch (error) {
throw createError({
statusCode: 400,
message: 'Invalid request body format',
});
}
const validatedBody = createListSchema.parse(parsedBody);
try {
const result = await prisma.$transaction(async tx => {
// App-level guard for a clean 409 message
const existing = await tx.lists.findFirst({
where: { user_id: userId, name: validatedBody.name },
});
if (existing) {
throw createError({ statusCode: 409, message: 'A list with this name already exists' });
}
const now = new Date();
const newList = await tx.lists.create({
data: {
id: uuidv7(),
user_id: userId,
name: validatedBody.name,
description: validatedBody.description || null,
public: validatedBody.public || false,
updated_at: now,
},
});
if (validatedBody.items && validatedBody.items.length > 0) {
await tx.list_items.createMany({
data: validatedBody.items.map(item => ({
id: uuidv7(),
list_id: newList.id,
tmdb_id: item.tmdb_id,
type: item.type,
})),
skipDuplicates: true,
});
}
return tx.lists.findUnique({
relationLoadStrategy: 'join',
where: { id: newList.id },
include: { list_items: true },
});
});
return {
list: result,
message: 'List created successfully',
};
} catch (err: any) {
// DB-level safety net: catch unique constraint violation from @@unique([user_id, name])
if (err.code === 'P2002') {
throw createError({ statusCode: 409, message: 'A list with this name already exists' });
}
throw err;
}
});