import SQL from 'sql-template-strings'; import { ulid } from 'ulid'; import { PermissionAreas } from '#shared/helpers.ts'; import type { NounClassInstance, NounWord, NounWords, NounWordsRaw } from '#shared/nouns.ts'; import { auditLog } from '~~/server/audit.ts'; import { getLocale, loadConfig } from '~~/server/data.ts'; import { approveNounEntry } from '~~/server/nouns.ts'; import { isAllowedToPost } from '~~/server/user.ts'; const minimizeWords = (words: NounWords): NounWordsRaw => { return Object.fromEntries(Object.entries(words) .map(([gender, wordsOfGender]) => { return [gender, Object.fromEntries(Object.entries(wordsOfGender) .map(([numerus, wordsOfNumerus]) => { return [numerus, wordsOfNumerus.map((word): NounWord | string => { if (!word.convention && !word.declension) { return word.spelling; } return word; })] as const; }) .filter(([_, wordsOfNumerus]) => wordsOfNumerus.length > 0))] as const; }) .filter(([_, wordsOfGender]) => { return Object.keys(wordsOfGender).length > 0; })); }; const generateKey = (words: NounWords, classInstance: NounClassInstance | null): string => { const defaultStem = classInstance?.stems.default; if (defaultStem) { return defaultStem.toLowerCase(); } const word = Object.values(words) .map((wordsByNumerus) => wordsByNumerus.singular?.[0]) .find((word) => word !== undefined); return word?.spelling.toLowerCase() ?? ''; }; export default defineEventHandler(async (event) => { const locale = getLocale(event); checkIsConfigEnabledOr404(await loadConfig(locale), 'nouns'); const { user, isGranted } = await useAuthentication(event); const db = useDatabase(); if (!user || !await isAllowedToPost(db, user)) { throw createError({ status: 401, statusMessage: 'Unauthorised', }); } const body = await readBody(event); const id = ulid(); await db.get(SQL` INSERT INTO nouns ( id, key, words, classInstance, categories, sources, approved, base_id, locale, author_id ) VALUES ( ${id}, ${generateKey(body.words, body.classInstance)}, ${JSON.stringify(minimizeWords(body.words))}, ${body.classInstance ? JSON.stringify(body.classInstance) : null}, ${body.categories.join('|')}, ${body.sources ? body.sources.join(',') : null}, 0, ${body.base}, ${locale}, ${user.id} ) `); await auditLog({ user }, 'nouns/submitted', body); if (isGranted(PermissionAreas.Nouns)) { await approveNounEntry(db, id, locale); await auditLog({ user }, 'nouns/approved', { id }); } setResponseStatus(event, 201, 'Created'); });