import fs from 'node:fs/promises' import path from 'node:path' import { prisma } from '../../lib/prisma.js' import { persistMultipartImages } from '../../lib/upload-images.js' import { formatFileTooLargeMessage, getProductImageMaxFileBytes, isMultipartFileTooLargeError, } from '../../lib/upload-limits.js' export async function registerAdminGalleryRoutes(fastify) { fastify.get( '/api/admin/gallery', { preHandler: [fastify.verifyAdmin] }, async () => { const items = await prisma.galleryImage.findMany({ orderBy: { createdAt: 'desc' }, }) return { items } }, ) fastify.post( '/api/admin/gallery/upload', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => { try { const urls = await persistMultipartImages(request, { maxFiles: 10, maxFileBytes: getProductImageMaxFileBytes(), subdir: '', eager: false, }) for (const url of urls) { await prisma.galleryImage.create({ data: { url, isResized: false }, }) } return { urls } } catch (error) { let message = error instanceof Error ? error.message : 'Не удалось загрузить файлы' let statusCode = error && typeof error === 'object' && 'statusCode' in error && Number.isInteger(error.statusCode) ? Number(error.statusCode) : 400 if (isMultipartFileTooLargeError(error)) { message = formatFileTooLargeMessage(getProductImageMaxFileBytes()) statusCode = 413 } return reply.code(statusCode).send({ error: message }) } }, ) fastify.delete( '/api/admin/gallery/:id', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => { const { id } = request.params const row = await prisma.galleryImage.findUnique({ where: { id } }) if (!row) { return reply.code(404).send({ error: 'Не найдено' }) } const usedInImages = await prisma.productImage.count({ where: { url: row.url } }) const usedAsLegacy = await prisma.product.count({ where: { imageUrl: row.url } }) if (usedInImages > 0 || usedAsLegacy > 0) { return reply.code(409).send({ error: 'Изображение используется в карточке товара' }) } const relative = row.url.replace(/^\//, '') const filePath = path.join(process.cwd(), relative) try { await fs.unlink(filePath) } catch (err) { if (err && typeof err === 'object' && 'code' in err && err.code !== 'ENOENT') { throw err } } await prisma.galleryImage.delete({ where: { id } }) return reply.code(204).send() }, ) }