import { z } from 'zod' import { checkRateLimit } from '~/server/utils/rateLimit' const ReferenceSchema = z.object({ titre: z.string().min(3, 'Minimum 3 caractères').max(200, 'Maximum 200 caractères').trim(), auteur: z.string().min(2, 'Minimum 2 caractères').max(200, 'Maximum 200 caractères').trim(), url: z.string().url('URL invalide').optional().or(z.literal('')).transform(v => v || undefined), description: z.string().min(50, 'Minimum 50 caractères').max(1000, 'Maximum 1000 caractères').trim(), pertinence_rag: z.string().max(500, 'Maximum 500 caractères').optional().transform(v => v?.trim() || undefined), hashtags: z.string().max(300, 'Maximum 300 caractères').optional().transform(v => v?.trim() || undefined), submitted_by_email: z.string().email('Email invalide').optional().or(z.literal('')).transform(v => v || undefined), }) export type ReferenceInput = z.infer export default defineEventHandler(async (event) => { const ip = getHeader(event, 'x-forwarded-for')?.split(',')[0].trim() || event.node.req.socket?.remoteAddress || '0.0.0.0' const allowed = await checkRateLimit(ip, 'submit-reference', 3) if (!allowed) { throw createError({ statusCode: 429, statusMessage: 'Trop de soumissions. Réessaie demain.' }) } const body = await readBody(event) const parsed = ReferenceSchema.safeParse(body) if (!parsed.success) { throw createError({ statusCode: 422, statusMessage: 'Validation échouée', data: parsed.error.flatten().fieldErrors, }) } const data = parsed.data const payload: Record = { titre: data.titre, auteur: data.auteur, url: data.url || null, description: data.description, pertinence_rag: data.pertinence_rag || null, hashtags: data.hashtags ? data.hashtags.split(',').map(h => h.trim()).filter(Boolean).join(',') : null, submitted_by_email: data.submitted_by_email || null, moderation_status: 'pending', submitted_at: new Date().toISOString(), } const config = useRuntimeConfig() const insertUrl = `${config.nocodbUrl}/api/v1/db/data/noco/${config.nocodbBase}/${config.referencesTableId}` let insertedRecord: any try { insertedRecord = await $fetch(insertUrl, { method: 'POST', headers: { 'xc-token': config.nocodbToken, 'Content-Type': 'application/json', }, body: JSON.stringify(payload), }) } catch (e: any) { console.error('[reference] Erreur NocoDB insert:', e?.message ?? e) throw createError({ statusCode: 502, statusMessage: 'Erreur serveur — réessaie dans quelques instants.' }) } const referenceId = insertedRecord?.Id ?? insertedRecord?.id ?? null return { status: 201, referenceId, message: 'Ta référence est en attente de modération.', } })