import * as m from '$lib/paraglide/messages.js'; /** * Mirror of the backend ErrorCode enum. * Keep in sync with backend/src/main/java/org/raddatz/familienarchiv/exception/ErrorCode.java */ export type ErrorCode = | 'PERSON_NOT_FOUND' | 'ALIAS_NOT_FOUND' | 'INVALID_PERSON_TYPE' | 'DOCUMENT_NOT_FOUND' | 'DOCUMENT_NO_FILE' | 'FILE_NOT_FOUND' | 'FILE_UPLOAD_FAILED' | 'UNSUPPORTED_FILE_TYPE' | 'USER_NOT_FOUND' | 'EMAIL_ALREADY_IN_USE' | 'WRONG_CURRENT_PASSWORD' | 'IMPORT_ALREADY_RUNNING' | 'INVALID_RESET_TOKEN' | 'INVITE_NOT_FOUND' | 'INVITE_EXHAUSTED' | 'INVITE_REVOKED' | 'INVITE_EXPIRED' | 'ANNOTATION_NOT_FOUND' | 'ANNOTATION_UPDATE_FAILED' | 'TRANSCRIPTION_BLOCK_NOT_FOUND' | 'TRANSCRIPTION_BLOCK_CONFLICT' | 'COMMENT_NOT_FOUND' | 'OCR_SERVICE_UNAVAILABLE' | 'OCR_JOB_NOT_FOUND' | 'OCR_DOCUMENT_NOT_UPLOADED' | 'OCR_PROCESSING_FAILED' | 'TRAINING_ALREADY_RUNNING' | 'OCR_TRAINING_CONFLICT' | 'INVALID_TAG_COLOR' | 'TAG_CYCLE_DETECTED' | 'TAG_NOT_FOUND' | 'TAG_MERGE_SELF' | 'TAG_MERGE_INVALID_TARGET' | 'MISSING_CREDENTIALS' | 'UNAUTHORIZED' | 'FORBIDDEN' | 'VALIDATION_ERROR' | 'BATCH_TOO_LARGE' | 'BULK_EDIT_TOO_MANY_IDS' | 'INTERNAL_ERROR'; export interface BackendError { code: ErrorCode; message: string; // English developer message — not shown to users } /** * Attempts to parse a backend ErrorResponse from a failed fetch response. * Returns null if the body is not valid JSON or does not contain a code field. */ export async function parseBackendError(res: Response): Promise { try { const body = await res.json(); if (body && typeof body.code === 'string') { return body as BackendError; } } catch { // Body was not JSON } return null; } /** Returns a localised message for the given error code via Paraglide. Falls back to INTERNAL_ERROR. */ export function getErrorMessage(code: ErrorCode | string | undefined): string { switch (code) { case 'PERSON_NOT_FOUND': return m.error_person_not_found(); case 'ALIAS_NOT_FOUND': return m.error_alias_not_found(); case 'INVALID_PERSON_TYPE': return m.error_invalid_person_type(); case 'DOCUMENT_NOT_FOUND': return m.error_document_not_found(); case 'DOCUMENT_NO_FILE': return m.error_document_no_file(); case 'FILE_NOT_FOUND': return m.error_file_not_found(); case 'FILE_UPLOAD_FAILED': return m.error_file_upload_failed(); case 'UNSUPPORTED_FILE_TYPE': return m.error_unsupported_file_type(); case 'USER_NOT_FOUND': return m.error_user_not_found(); case 'EMAIL_ALREADY_IN_USE': return m.error_email_already_in_use(); case 'WRONG_CURRENT_PASSWORD': return m.error_wrong_current_password(); case 'IMPORT_ALREADY_RUNNING': return m.error_import_already_running(); case 'INVALID_RESET_TOKEN': return m.error_invalid_reset_token(); case 'INVITE_NOT_FOUND': return m.error_invite_not_found(); case 'INVITE_EXHAUSTED': return m.error_invite_exhausted(); case 'INVITE_REVOKED': return m.error_invite_revoked(); case 'INVITE_EXPIRED': return m.error_invite_expired(); case 'ANNOTATION_NOT_FOUND': return m.error_annotation_not_found(); case 'ANNOTATION_UPDATE_FAILED': return m.error_annotation_update_failed(); case 'TRANSCRIPTION_BLOCK_NOT_FOUND': return m.error_transcription_block_not_found(); case 'TRANSCRIPTION_BLOCK_CONFLICT': return m.error_transcription_block_conflict(); case 'COMMENT_NOT_FOUND': return m.error_comment_not_found(); case 'OCR_SERVICE_UNAVAILABLE': return m.error_ocr_service_unavailable(); case 'OCR_JOB_NOT_FOUND': return m.error_ocr_job_not_found(); case 'OCR_DOCUMENT_NOT_UPLOADED': return m.error_ocr_document_not_uploaded(); case 'OCR_PROCESSING_FAILED': return m.error_ocr_processing_failed(); case 'TRAINING_ALREADY_RUNNING': return m.error_training_already_running(); case 'OCR_TRAINING_CONFLICT': return m.error_internal_error(); case 'INVALID_TAG_COLOR': return m.error_invalid_tag_color(); case 'TAG_CYCLE_DETECTED': return m.error_tag_cycle_detected(); case 'TAG_NOT_FOUND': return m.error_tag_not_found(); case 'TAG_MERGE_SELF': return m.error_tag_merge_self(); case 'TAG_MERGE_INVALID_TARGET': return m.error_tag_merge_invalid_target(); case 'MISSING_CREDENTIALS': return m.login_error_missing_credentials(); case 'UNAUTHORIZED': return m.error_unauthorized(); case 'FORBIDDEN': return m.error_forbidden(); case 'VALIDATION_ERROR': return m.error_validation_error(); case 'BATCH_TOO_LARGE': return m.error_batch_too_large(); case 'BULK_EDIT_TOO_MANY_IDS': return m.error_bulk_edit_too_many_ids(); default: return m.error_internal_error(); } }