Files
family_wishlist/apps/backend/src/modules/profile/profile.routes.ts
2026-04-26 23:29:20 +03:00

66 lines
2.2 KiB
TypeScript

import type { FastifyInstance } from 'fastify';
import { updateProfileSchema } from '@family-wishlist/shared';
import { ConflictError, NotFoundError, ValidationError } from '../../utils/errors.js';
import { Prisma } from '@prisma/client';
import { deleteLocalImageIfAny, saveUploadedAvatar } from '../images/storage.service.js';
import { usersRegistry } from '../../auth/users.registry.js';
const MAX_AVATAR_BYTES = 2 * 1024 * 1024;
export default async function profileRoutes(app: FastifyInstance) {
app.addHook('preHandler', app.authenticate);
app.get('/', async (request) => {
const profile = await app.prisma.user.findUnique({ where: { id: request.user.id } });
if (!profile) throw new NotFoundError('Profile');
return profile;
});
app.get('/friend', async (request) => {
const friend = usersRegistry.all().find((u) => u.id !== request.user.id);
if (!friend) return null;
return app.prisma.user.findUnique({
where: { id: friend.id },
select: { slug: true, displayName: true, avatarUrl: true },
});
});
app.patch('/', async (request) => {
const body = updateProfileSchema.parse(request.body);
try {
const updated = await app.prisma.user.update({
where: { id: request.user.id },
data: body,
});
return updated;
} catch (err) {
if (err instanceof Prisma.PrismaClientKnownRequestError && err.code === 'P2002') {
throw new ConflictError('Slug is already taken');
}
throw err;
}
});
app.post('/avatar', async (request) => {
const current = await app.prisma.user.findUnique({ where: { id: request.user.id } });
if (!current) throw new NotFoundError('Profile');
const data = await request.file();
if (!data) throw new ValidationError('No file uploaded');
const buffer = await data.toBuffer();
if (buffer.byteLength > MAX_AVATAR_BYTES) {
throw new ValidationError('Avatar must be 2 MB or less');
}
const { imageUrl } = await saveUploadedAvatar(request.user.id, data.mimetype, buffer);
await deleteLocalImageIfAny(current.avatarUrl);
return app.prisma.user.update({
where: { id: request.user.id },
data: { avatarUrl: imageUrl },
});
});
}