import type { H3Event } from 'h3' export interface ReviewRow { id: number title: string | null date: string | null author_or_director: string | null review: string | null medium: SelectOption | null } interface SelectOption { id: number value: string } interface Field { name: string select_options?: SelectOption[] } const OPTION_CACHE_MS = 10 * 60_000 let mediumOptions: { ids: Partial>, fetchedAt: number } | null = null function toMedium(value: string | undefined): Medium | null { return MEDIUM_KEYS.find(medium => MEDIUMS[medium].label === value) ?? null } export function toReview(row: ReviewRow): Review { return { id: row.id, date: row.date ?? '', title: (row.title ?? '').trim(), author: row.author_or_director?.trim() || null, text: (row.review ?? '').replace(/ /g, ' ').trim(), medium: toMedium(row.medium?.value) } } export async function mediumOptionId(event: H3Event, medium: Medium): Promise { if (!mediumOptions || Date.now() - mediumOptions.fetchedAt > OPTION_CACHE_MS) { const fields = await listFields(event, 'reviews') const options = fields.find(field => field.name === 'medium')?.select_options ?? [] const ids: Partial> = {} for (const option of options) { const key = toMedium(option.value) if (key) ids[key] = option.id } mediumOptions = { ids, fetchedAt: Date.now() } } const id = mediumOptions.ids[medium] if (!id) { throw createError({ statusCode: 500, statusMessage: `The medium field has no "${MEDIUMS[medium].label}" option` }) } return id }