import { prisma } from '../../lib/prisma.js' function validateBlockPayload(body, reply) { const key = String(body?.key || '').trim() const title = String(body?.title || '').trim() const content = String(body?.body || '').trim() const sort = Number(body?.sort ?? 0) const published = body?.published === undefined ? true : Boolean(body.published) if (!key) return reply.code(400).send({ error: 'key обязателен' }) if (!/^[a-z0-9_-]{2,60}$/i.test(key)) { return reply.code(400).send({ error: 'key должен быть 2-60 символов: буквы, цифры, "_" или "-"' }) } if (!title) return reply.code(400).send({ error: 'title обязателен' }) if (title.length > 120) return reply.code(400).send({ error: 'title максимум 120 символов' }) if (!content) return reply.code(400).send({ error: 'body обязателен' }) if (content.length > 5000) return reply.code(400).send({ error: 'body максимум 5000 символов' }) if (!Number.isFinite(sort) || Math.abs(sort) > 10_000) return reply.code(400).send({ error: 'Некорректный sort' }) return { key, title, body: content, sort: Math.trunc(sort), published } } export async function registerInfoPageRoutes(fastify) { fastify.get('/api/info-page/blocks', async () => { const items = await prisma.infoPageBlock.findMany({ where: { published: true }, orderBy: [{ sort: 'asc' }, { createdAt: 'asc' }], }) return { items } }) fastify.get( '/api/admin/info-page/blocks', { preHandler: [fastify.verifyAdmin] }, async () => { const items = await prisma.infoPageBlock.findMany({ orderBy: [{ sort: 'asc' }, { createdAt: 'asc' }] }) return { items } }, ) fastify.post( '/api/admin/info-page/blocks', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => { const validated = validateBlockPayload(request.body, reply) if (!validated) return try { const item = await prisma.infoPageBlock.create({ data: validated }) return reply.code(201).send({ item }) } catch { return reply.code(409).send({ error: 'Блок с таким key уже существует' }) } }, ) fastify.patch( '/api/admin/info-page/blocks/:id', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => { const { id } = request.params const existing = await prisma.infoPageBlock.findUnique({ where: { id } }) if (!existing) return reply.code(404).send({ error: 'Блок не найден' }) const body = request.body ?? {} const data = {} if (body.key !== undefined) { const key = String(body.key || '').trim() if (!key) return reply.code(400).send({ error: 'key обязателен' }) if (!/^[a-z0-9_-]{2,60}$/i.test(key)) { return reply.code(400).send({ error: 'key должен быть 2-60 символов: буквы, цифры, "_" или "-"' }) } data.key = key } if (body.title !== undefined) { const title = String(body.title || '').trim() if (!title) return reply.code(400).send({ error: 'title обязателен' }) if (title.length > 120) return reply.code(400).send({ error: 'title максимум 120 символов' }) data.title = title } if (body.body !== undefined) { const content = String(body.body || '').trim() if (!content) return reply.code(400).send({ error: 'body обязателен' }) if (content.length > 5000) return reply.code(400).send({ error: 'body максимум 5000 символов' }) data.body = content } if (body.sort !== undefined) { const sort = Number(body.sort) if (!Number.isFinite(sort) || Math.abs(sort) > 10_000) return reply.code(400).send({ error: 'Некорректный sort' }) data.sort = Math.trunc(sort) } if (body.published !== undefined) { data.published = Boolean(body.published) } try { const item = await prisma.infoPageBlock.update({ where: { id }, data }) return { item } } catch { return reply.code(409).send({ error: 'Блок с таким key уже существует' }) } }, ) fastify.delete( '/api/admin/info-page/blocks/:id', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => { const { id } = request.params try { await prisma.infoPageBlock.delete({ where: { id } }) return reply.code(204).send() } catch { return reply.code(404).send({ error: 'Блок не найден' }) } }, ) }