refactor: upgrade to Zod v4 (#623)

This commit is contained in:
Elias Schneider
2025-06-08 15:44:59 +02:00
committed by GitHub
parent 9a4aab465a
commit 388a874922
18 changed files with 270 additions and 51 deletions

View File

@@ -9,7 +9,7 @@
import { preventDefault } from '$lib/utils/event-util';
import { createForm } from '$lib/utils/form-util';
import { toast } from 'svelte-sonner';
import { z } from 'zod';
import { z } from 'zod/v4';
let {
callback,
@@ -35,7 +35,7 @@
.min(2)
.max(30)
.regex(/^[a-z0-9_@.-]+$/, m.username_can_only_contain()),
email: z.string().email(),
email: z.email(),
isAdmin: z.boolean()
});
type FormSchema = typeof formSchema;

View File

@@ -1,8 +1,9 @@
<script lang="ts">
import * as Select from '$lib/components/ui/select';
import { getLocale, setLocale, type Locale } from '$lib/paraglide/runtime';
import { getLocale, type Locale } from '$lib/paraglide/runtime';
import UserService from '$lib/services/user-service';
import userStore from '$lib/stores/user-store';
import { setLocale } from '$lib/utils/locale.util';
const userService = new UserService();
const currentLocale = getLocale();

View File

@@ -5,7 +5,7 @@
import type { ApiKeyCreate } from '$lib/types/api-key.type';
import { preventDefault } from '$lib/utils/event-util';
import { createForm } from '$lib/utils/form-util';
import { z } from 'zod';
import { z } from 'zod/v4';
let {
callback
@@ -28,8 +28,8 @@
const formSchema = z.object({
name: z
.string()
.min(3, m.name_must_be_at_least_3_characters())
.max(50, m.name_cannot_exceed_50_characters()),
.min(3)
.max(50),
description: z.string().default(''),
expiresAt: z.date().min(new Date(), m.expiration_date_must_be_in_the_future())
});

View File

@@ -12,7 +12,7 @@
import { preventDefault } from '$lib/utils/event-util';
import { createForm } from '$lib/utils/form-util';
import { toast } from 'svelte-sonner';
import { z } from 'zod';
import { z } from 'zod/v4';
let {
callback,
@@ -36,7 +36,7 @@
smtpPort: z.number().min(1),
smtpUser: z.string(),
smtpPassword: z.string(),
smtpFrom: z.string().email(),
smtpFrom: z.email(),
smtpTls: z.enum(['none', 'starttls', 'tls']),
smtpSkipCertVerify: z.boolean(),
emailOneTimeAccessAsUnauthenticatedEnabled: z.boolean(),

View File

@@ -8,7 +8,7 @@
import { preventDefault } from '$lib/utils/event-util';
import { createForm } from '$lib/utils/form-util';
import { toast } from 'svelte-sonner';
import { z } from 'zod';
import { z } from 'zod/v4';
let {
callback,

View File

@@ -10,7 +10,7 @@
import { preventDefault } from '$lib/utils/event-util';
import { createForm } from '$lib/utils/form-util';
import { toast } from 'svelte-sonner';
import { z } from 'zod';
import { z } from 'zod/v4';
let {
callback,
@@ -48,7 +48,7 @@
};
const formSchema = z.object({
ldapUrl: z.string().url(),
ldapUrl: z.url(),
ldapBindDn: z.string().min(1),
ldapBindPassword: z.string().min(1),
ldapBase: z.string().min(1),

View File

@@ -8,16 +8,18 @@
import { LucideMinus, LucidePlus } from '@lucide/svelte';
import type { Snippet } from 'svelte';
import type { HTMLAttributes } from 'svelte/elements';
import { z } from 'zod/v4';
let {
client,
federatedIdentities = $bindable([]),
error = $bindable(null),
errors,
...restProps
}: HTMLAttributes<HTMLDivElement> & {
client?: OidcClient;
federatedIdentities: OidcClientFederatedIdentity[];
error?: string | null;
errors?: z.core.$ZodIssue[];
children?: Snippet;
} = $props();
@@ -47,6 +49,13 @@
[field]: value
};
}
function getFieldError(index: number, field: keyof OidcClientFederatedIdentity): string | null {
console.log(federatedIdentities)
if (!errors) return null;
const path = [index, field];
return errors?.filter((e) => e.path[0] == path[0] && e.path[1] == path[1])[0]?.message;
}
</script>
<div {...restProps}>
@@ -76,8 +85,11 @@
placeholder="https://example.com/"
value={identity.issuer}
oninput={(e) => updateFederatedIdentity(i, 'issuer', e.currentTarget.value)}
required
aria-invalid={!!getFieldError(i, 'issuer')}
/>
{#if getFieldError(i, 'issuer')}
<p class="text-destructive mt-1 text-xs">{getFieldError(i, 'issuer')}</p>
{/if}
</div>
<div>
@@ -87,7 +99,11 @@
placeholder="Defaults to the client ID: {client?.id}"
value={identity.subject || ''}
oninput={(e) => updateFederatedIdentity(i, 'subject', e.currentTarget.value)}
aria-invalid={!!getFieldError(i, 'subject')}
/>
{#if getFieldError(i, 'subject')}
<p class="text-destructive mt-1 text-xs">{getFieldError(i, 'subject')}</p>
{/if}
</div>
<div>
@@ -97,7 +113,11 @@
placeholder="Defaults to the Pocket ID URL"
value={identity.audience || ''}
oninput={(e) => updateFederatedIdentity(i, 'audience', e.currentTarget.value)}
aria-invalid={!!getFieldError(i, 'audience')}
/>
{#if getFieldError(i, 'audience')}
<p class="text-destructive mt-1 text-xs">{getFieldError(i, 'audience')}</p>
{/if}
</div>
<div>
@@ -107,7 +127,11 @@
placeholder="Defaults to {identity.issuer || '<issuer>'}/.well-known/jwks.json"
value={identity.jwks || ''}
oninput={(e) => updateFederatedIdentity(i, 'jwks', e.currentTarget.value)}
aria-invalid={!!getFieldError(i, 'jwks')}
/>
{#if getFieldError(i, 'jwks')}
<p class="text-destructive mt-1 text-xs">{getFieldError(i, 'jwks')}</p>
{/if}
</div>
</div>
</div>
@@ -115,10 +139,6 @@
</div>
</FormInput>
{#if error}
<p class="text-destructive mt-1 text-xs">{error}</p>
{/if}
<Button class="mt-3" variant="secondary" size="sm" onclick={addFederatedIdentity} type="button">
<LucidePlus class="mr-1 size-4" />
{federatedIdentities.length === 0

View File

@@ -11,7 +11,7 @@
import { cn } from '$lib/utils/style';
import { LucideChevronDown } from '@lucide/svelte';
import { slide } from 'svelte/transition';
import { z } from 'zod';
import { z } from 'zod/v4';
import FederatedIdentitiesInput from './federated-identities-input.svelte';
import OidcCallbackUrlInput from './oidc-callback-url-input.svelte';
@@ -50,17 +50,17 @@
credentials: z.object({
federatedIdentities: z.array(
z.object({
issuer: z.string().url(),
issuer: z.url(),
subject: z.string().optional(),
audience: z.string().optional(),
jwks: z.string().url().optional().or(z.literal(''))
jwks: z.url().optional().or(z.literal(''))
})
)
})
});
type FormSchema = typeof formSchema;
const { inputs, ...form } = createForm<FormSchema>(formSchema, client);
const { inputs, errors, ...form } = createForm<FormSchema>(formSchema, client);
async function onSubmit() {
const data = form.validate();
@@ -91,6 +91,15 @@
logo = null;
logoDataURL = null;
}
function getFederatedIdentityErrors(errors: z.ZodError<any> | undefined) {
return errors?.issues
.filter((e) => e.path[0] == 'credentials' && e.path[1] == 'federatedIdentities')
.map((e) => {
e.path.splice(0, 2);
return e;
});
}
</script>
<form onsubmit={preventDefault(onSubmit)}>
@@ -159,7 +168,7 @@
<FederatedIdentitiesInput
client={existingClient}
bind:federatedIdentities={$inputs.credentials.value.federatedIdentities}
bind:error={$inputs.credentials.error}
errors={getFederatedIdentityErrors($errors)}
/>
</div>
{/if}

View File

@@ -6,7 +6,7 @@
import type { UserGroupCreate } from '$lib/types/user-group.type';
import { preventDefault } from '$lib/utils/event-util';
import { createForm } from '$lib/utils/form-util';
import { z } from 'zod';
import { z } from 'zod/v4';
let {
callback,

View File

@@ -7,7 +7,7 @@
import type { User, UserCreate } from '$lib/types/user.type';
import { preventDefault } from '$lib/utils/event-util';
import { createForm } from '$lib/utils/form-util';
import { z } from 'zod';
import { z } from 'zod/v4';
let {
callback,
@@ -37,7 +37,7 @@
.min(2)
.max(30)
.regex(/^[a-z0-9_@.-]+$/, m.username_can_only_contain()),
email: z.string().email(),
email: z.email(),
isAdmin: z.boolean(),
disabled: z.boolean()
});