import type { FastifyInstance } from 'fastify'; import { MAX_UPLOAD_BYTES } from '../../plugins/multipart.js'; import { WishesService } from '../wishes/wishes.service.js'; import { ValidationError } from '../../utils/errors.js'; import { deleteLocalImageIfAny, saveUploadedImage } from './storage.service.js'; import { fetchOgImageForWish } from './og.service.js'; export default async function imagesRoutes(app: FastifyInstance) { app.addHook('preHandler', app.authenticate); const wishes = new WishesService(app.prisma); app.post('/:id/image', async (request) => { const { id } = request.params as { id: string }; const current = await wishes.getOwned(request.user.id, id); const data = await request.file(); if (!data) throw new ValidationError('No file uploaded'); const buffer = await data.toBuffer(); if (buffer.byteLength > MAX_UPLOAD_BYTES) { throw new ValidationError('File too large'); } const { imageUrl } = await saveUploadedImage(id, data.mimetype, buffer); await deleteLocalImageIfAny(current.imageUrl); return app.prisma.wish.update({ where: { id }, data: { imageUrl, imageSource: 'UPLOADED' }, }); }); app.post('/:id/image/refresh-og', async (request) => { const { id } = request.params as { id: string }; const wish = await wishes.getOwned(request.user.id, id); if (!wish.url) throw new ValidationError('Wish has no url'); await fetchOgImageForWish(app, id, wish.url); return app.prisma.wish.findUniqueOrThrow({ where: { id } }); }); app.delete('/:id/image', async (request) => { const { id } = request.params as { id: string }; const wish = await wishes.getOwned(request.user.id, id); await deleteLocalImageIfAny(wish.imageUrl); return app.prisma.wish.update({ where: { id }, data: { imageUrl: null, imageSource: 'DEFAULT' }, }); }); }