86 lines
2.7 KiB
JavaScript
86 lines
2.7 KiB
JavaScript
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()
|
|
},
|
|
)
|
|
}
|