From 327fd89cb908f14309b8dc851376c2347c46c62b Mon Sep 17 00:00:00 2001 From: Marcel Date: Sun, 26 Apr 2026 10:22:52 +0200 Subject: [PATCH] refactor(persons): centralise PersonType, PERSON_TYPES and normalizePersonType in person-validation Removes four independent PersonType type declarations and the duplicated TYPES/PERSON_TYPES arrays. normalizePersonType moves from the edit route module into the shared lib so page.server.test.ts no longer imports from a route. Both server actions now use normalizePersonType for personType extraction instead of an inline type cast. Co-Authored-By: Claude Sonnet 4.6 --- .../src/lib/components/PersonTypeSelector.svelte | 4 +--- frontend/src/lib/person-validation.ts | 7 +++++++ .../src/routes/persons/[id]/edit/+page.server.ts | 14 ++------------ .../routes/persons/[id]/edit/PersonEditForm.svelte | 4 +--- .../routes/persons/[id]/edit/page.server.test.ts | 2 +- frontend/src/routes/persons/new/+page.server.ts | 8 ++------ frontend/src/routes/persons/new/+page.svelte | 4 +--- 7 files changed, 15 insertions(+), 28 deletions(-) diff --git a/frontend/src/lib/components/PersonTypeSelector.svelte b/frontend/src/lib/components/PersonTypeSelector.svelte index 253c5673..bd77c6a1 100644 --- a/frontend/src/lib/components/PersonTypeSelector.svelte +++ b/frontend/src/lib/components/PersonTypeSelector.svelte @@ -2,9 +2,7 @@ import { untrack } from 'svelte'; import { radioGroupNav } from '$lib/actions/radioGroupNav'; import { m } from '$lib/paraglide/messages.js'; - -const TYPES = ['PERSON', 'INSTITUTION', 'GROUP', 'UNKNOWN'] as const; -type PersonType = (typeof TYPES)[number]; +import { PERSON_TYPES as TYPES, type PersonType } from '$lib/person-validation'; let { value = 'PERSON', diff --git a/frontend/src/lib/person-validation.ts b/frontend/src/lib/person-validation.ts index 5a43443f..72916502 100644 --- a/frontend/src/lib/person-validation.ts +++ b/frontend/src/lib/person-validation.ts @@ -1,3 +1,10 @@ +export const PERSON_TYPES = ['PERSON', 'INSTITUTION', 'GROUP', 'UNKNOWN'] as const; +export type PersonType = (typeof PERSON_TYPES)[number]; + +export function normalizePersonType(raw: string | undefined | null): PersonType { + return raw === 'SKIP' ? 'UNKNOWN' : ((raw ?? 'PERSON') as PersonType); +} + export function validatePersonFields( personType: string, firstName: string | undefined | null, diff --git a/frontend/src/routes/persons/[id]/edit/+page.server.ts b/frontend/src/routes/persons/[id]/edit/+page.server.ts index 34e8560a..0d4d988c 100644 --- a/frontend/src/routes/persons/[id]/edit/+page.server.ts +++ b/frontend/src/routes/persons/[id]/edit/+page.server.ts @@ -1,13 +1,7 @@ import { error, fail, redirect } from '@sveltejs/kit'; import { createApiClient } from '$lib/api.server'; import { getErrorMessage } from '$lib/errors'; -import { validatePersonFields } from '$lib/person-validation'; - -type PersonType = 'PERSON' | 'INSTITUTION' | 'GROUP' | 'UNKNOWN' | 'SKIP'; - -export function normalizePersonType(raw: string | undefined | null): Exclude { - return raw === 'SKIP' ? 'UNKNOWN' : ((raw ?? 'PERSON') as Exclude); -} +import { normalizePersonType, validatePersonFields } from '$lib/person-validation'; export async function load({ params, fetch, locals }) { const canWrite = @@ -37,11 +31,7 @@ export async function load({ params, fetch, locals }) { export const actions = { update: async ({ request, params, fetch }) => { const formData = await request.formData(); - const personType = (formData.get('personType')?.toString() ?? 'PERSON') as - | 'PERSON' - | 'INSTITUTION' - | 'GROUP' - | 'UNKNOWN'; + const personType = normalizePersonType(formData.get('personType')?.toString()); const title = formData.get('title')?.toString().trim() || undefined; const firstName = formData.get('firstName')?.toString().trim(); const lastName = formData.get('lastName')?.toString().trim(); diff --git a/frontend/src/routes/persons/[id]/edit/PersonEditForm.svelte b/frontend/src/routes/persons/[id]/edit/PersonEditForm.svelte index f583f9ec..627ec47b 100644 --- a/frontend/src/routes/persons/[id]/edit/PersonEditForm.svelte +++ b/frontend/src/routes/persons/[id]/edit/PersonEditForm.svelte @@ -2,8 +2,7 @@ import { untrack } from 'svelte'; import { m } from '$lib/paraglide/messages.js'; import PersonTypeSelector from '$lib/components/PersonTypeSelector.svelte'; - -type PersonType = 'PERSON' | 'INSTITUTION' | 'GROUP' | 'UNKNOWN'; +import { PERSON_TYPES as TYPES, type PersonType } from '$lib/person-validation'; let { person @@ -20,7 +19,6 @@ let { }; } = $props(); -const TYPES = ['PERSON', 'INSTITUTION', 'GROUP', 'UNKNOWN'] as const; let selectedType = $state( untrack(() => TYPES.includes(person.personType as PersonType) ? (person.personType as PersonType) : 'PERSON' diff --git a/frontend/src/routes/persons/[id]/edit/page.server.test.ts b/frontend/src/routes/persons/[id]/edit/page.server.test.ts index 83688903..f8f49194 100644 --- a/frontend/src/routes/persons/[id]/edit/page.server.test.ts +++ b/frontend/src/routes/persons/[id]/edit/page.server.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest'; -import { normalizePersonType } from './+page.server'; +import { normalizePersonType } from '$lib/person-validation'; describe('edit load — SKIP → UNKNOWN normalization', () => { it('maps SKIP to UNKNOWN', () => { diff --git a/frontend/src/routes/persons/new/+page.server.ts b/frontend/src/routes/persons/new/+page.server.ts index ed828591..4cde5cb8 100644 --- a/frontend/src/routes/persons/new/+page.server.ts +++ b/frontend/src/routes/persons/new/+page.server.ts @@ -1,7 +1,7 @@ import { error, fail, redirect } from '@sveltejs/kit'; import { createApiClient } from '$lib/api.server'; import { getErrorMessage } from '$lib/errors'; -import { validatePersonFields } from '$lib/person-validation'; +import { normalizePersonType, validatePersonFields } from '$lib/person-validation'; export async function load({ locals }: { locals: App.Locals }) { const canWrite = @@ -14,11 +14,7 @@ export async function load({ locals }: { locals: App.Locals }) { export const actions = { default: async ({ request, fetch }) => { const formData = await request.formData(); - const personType = (formData.get('personType')?.toString() ?? 'PERSON') as - | 'PERSON' - | 'INSTITUTION' - | 'GROUP' - | 'UNKNOWN'; + const personType = normalizePersonType(formData.get('personType')?.toString()); const title = formData.get('title')?.toString().trim() || undefined; const firstName = formData.get('firstName')?.toString().trim(); const lastName = formData.get('lastName')?.toString().trim(); diff --git a/frontend/src/routes/persons/new/+page.svelte b/frontend/src/routes/persons/new/+page.svelte index cda6e7f7..7f9ccc48 100644 --- a/frontend/src/routes/persons/new/+page.svelte +++ b/frontend/src/routes/persons/new/+page.svelte @@ -3,9 +3,7 @@ import { untrack } from 'svelte'; import { m } from '$lib/paraglide/messages.js'; import BackButton from '$lib/components/BackButton.svelte'; import PersonTypeSelector from '$lib/components/PersonTypeSelector.svelte'; - -type PersonType = 'PERSON' | 'INSTITUTION' | 'GROUP' | 'UNKNOWN'; -const TYPES = ['PERSON', 'INSTITUTION', 'GROUP', 'UNKNOWN'] as const; +import { PERSON_TYPES as TYPES, type PersonType } from '$lib/person-validation'; let { form } = $props();