refactor: extract validateGalleryImages helper

This commit is contained in:
Kirill
2026-05-27 21:41:33 +05:00
parent 6615d97203
commit 24b3b4063d
3 changed files with 64 additions and 28 deletions
@@ -0,0 +1,32 @@
import { describe, it, expect, vi } from 'vitest'
import { validateGalleryImages } from '../validate-gallery-images.js'
describe('validateGalleryImages', () => {
it('returns null when urls is empty', async () => {
const prisma = { galleryImage: { findMany: vi.fn() } }
const result = await validateGalleryImages(prisma, [])
expect(result).toBeNull()
})
it('throws 400 when image not found', async () => {
const prisma = { galleryImage: { findMany: vi.fn().mockResolvedValue([]) } }
await expect(validateGalleryImages(prisma, ['/uploads/missing.jpg'])).rejects.toMatchObject({ statusCode: 400 })
})
it('throws 400 when image not yet resized', async () => {
const prisma = {
galleryImage: { findMany: vi.fn().mockResolvedValue([{ url: '/uploads/img.jpg', isResized: false }]) },
}
await expect(validateGalleryImages(prisma, ['/uploads/img.jpg'])).rejects.toMatchObject({ statusCode: 400 })
})
it('returns existing images when all valid and resized', async () => {
const images = [
{ url: '/uploads/img1.jpg', isResized: true },
{ url: '/uploads/img2.jpg', isResized: true },
]
const prisma = { galleryImage: { findMany: vi.fn().mockResolvedValue(images) } }
const result = await validateGalleryImages(prisma, ['/uploads/img1.jpg', '/uploads/img2.jpg'])
expect(result).toEqual(images)
})
})
+23
View File
@@ -0,0 +1,23 @@
export async function validateGalleryImages(prisma, urls) {
if (!urls || urls.length === 0) return null
const existing = await prisma.galleryImage.findMany({
where: { url: { in: urls } },
select: { url: true, isResized: true },
})
const galleryMap = new Map(existing.map((g) => [g.url, g]))
const notFound = urls.filter((u) => !galleryMap.has(u))
if (notFound.length > 0) {
throw Object.assign(new Error(`Gallery images not found: ${notFound.join(', ')}`), { statusCode: 400 })
}
const notResized = urls.filter((u) => galleryMap.get(u) && !galleryMap.get(u).isResized)
if (notResized.length > 0) {
throw Object.assign(new Error('Some gallery images have not been processed yet. Please try again later.'), {
statusCode: 400,
})
}
return existing
}
+9 -28
View File
@@ -1,4 +1,5 @@
import { prisma } from '../../lib/prisma.js' import { prisma } from '../../lib/prisma.js'
import { validateGalleryImages } from '../../lib/validate-gallery-images.js'
const CREATE_PRODUCT_SCHEMA = { const CREATE_PRODUCT_SCHEMA = {
body: { body: {
@@ -87,20 +88,10 @@ export async function registerAdminProductRoutes(fastify) {
if (Array.isArray(body.imageUrls) && body.imageUrls.length > 0) { if (Array.isArray(body.imageUrls) && body.imageUrls.length > 0) {
const urls = body.imageUrls.map((u) => String(u || '').trim()).filter(Boolean) const urls = body.imageUrls.map((u) => String(u || '').trim()).filter(Boolean)
if (urls.length > 0) { if (urls.length > 0) {
const galleryImages = await prisma.galleryImage.findMany({ try {
where: { url: { in: urls } }, await validateGalleryImages(prisma, urls)
select: { url: true, isResized: true }, } catch (err) {
}) return reply.code(err.statusCode || 400).send({ error: err.message })
const galleryMap = new Map(galleryImages.map((g) => [g.url, g]))
const notFound = urls.filter((u) => !galleryMap.has(u))
const notResized = urls.filter((u) => galleryMap.get(u) && !galleryMap.get(u).isResized)
if (notFound.length > 0) {
return reply.code(400).send({ error: 'Некоторые изображения не найдены в галерее' })
}
if (notResized.length > 0) {
return reply
.code(400)
.send({ error: 'Изображения должны быть обработаны (resize) перед прикреплением к товару' })
} }
} }
} }
@@ -214,20 +205,10 @@ export async function registerAdminProductRoutes(fastify) {
if (body.imageUrls !== undefined && Array.isArray(body.imageUrls)) { if (body.imageUrls !== undefined && Array.isArray(body.imageUrls)) {
const urls = body.imageUrls.map((u) => String(u || '').trim()).filter(Boolean) const urls = body.imageUrls.map((u) => String(u || '').trim()).filter(Boolean)
if (urls.length > 0) { if (urls.length > 0) {
const galleryImages = await prisma.galleryImage.findMany({ try {
where: { url: { in: urls } }, await validateGalleryImages(prisma, urls)
select: { url: true, isResized: true }, } catch (err) {
}) return reply.code(err.statusCode || 400).send({ error: err.message })
const galleryMap = new Map(galleryImages.map((g) => [g.url, g]))
const notFound = urls.filter((u) => !galleryMap.has(u))
const notResized = urls.filter((u) => galleryMap.get(u) && !galleryMap.get(u).isResized)
if (notFound.length > 0) {
return reply.code(400).send({ error: 'Некоторые изображения не найдены в галерее' })
}
if (notResized.length > 0) {
return reply
.code(400)
.send({ error: 'Изображения должны быть обработаны (resize) перед прикреплением к товару' })
} }
} }
} }