PronounsPage/server/api/nouns/submit.post.ts

81 lines
2.9 KiB
TypeScript

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');
});