Skip to content

Commit bf31b5a

Browse files
committed
Realtime validation didn't work for Zod schemas without effects.
1 parent e3eec7b commit bf31b5a

File tree

6 files changed

+105
-6
lines changed

6 files changed

+105
-6
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ Headlines: Added, Changed, Deprecated, Removed, Fixed, Security
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.8.1] - 2023-04-24
9+
10+
### Fixed
11+
12+
- Realtime validation didn't work for Zod schemas without effects.
13+
814
## [0.8.0] - 2023-04-22
915

1016
### Changed

src/index.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,12 @@ test('FormData array data', async () => {
160160
});
161161

162162
test('Nullable values', async () => {
163-
const schema = z.object({
163+
const refinedSchema = z.object({
164164
scopeId: z.number().int().min(1),
165165
name: z.string().nullable()
166-
});
166+
}).refine(data => data);
167+
168+
const schema = refinedSchema._def.schema
167169

168170
const output = defaultData(schema);
169171
expect(output.scopeId).equals(0);

src/lib/client/index.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -915,11 +915,15 @@ async function validateField<T extends AnyZodObject, M>(
915915
const validationPath = path.filter((p) => isNaN(parseInt(p)));
916916

917917
function extractValidator(data: any, key: string) {
918-
const objectShape = data?._def?.schema?.shape;
919-
if (objectShape) return objectShape[key];
918+
const def = data?._def
920919

921-
const arrayShape = data?.element?.shape;
922-
if (arrayShape) return arrayShape[key];
920+
if(def) {
921+
const objectShape = 'shape' in def ? def.shape() : def.schema?.shape;
922+
if (objectShape) return objectShape[key];
923+
924+
const arrayShape = data?.element?.shape;
925+
if (arrayShape) return arrayShape[key];
926+
}
923927

924928
throw new SuperFormError(
925929
'Invalid Zod validator for ' + key + ': ' + data
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { fail } from '@sveltejs/kit';
2+
import type { Actions, PageServerLoad } from './$types';
3+
import { schema } from './schema';
4+
import { message, superValidate } from '$lib/server';
5+
6+
export const load = (async () => {
7+
// Server API:
8+
const form = await superValidate(schema);
9+
10+
// Always return { form } in load and form actions.
11+
return { form };
12+
}) satisfies PageServerLoad;
13+
14+
export const actions: Actions = {
15+
default: async ({ request }) => {
16+
const form = await superValidate(request, schema);
17+
console.log('POST', form);
18+
19+
// Convenient validation check:
20+
if (!form.valid) {
21+
// Again, always return { form } and things will just work.
22+
return fail(400, { form });
23+
}
24+
25+
return message(form, 'Success');
26+
}
27+
};

src/routes/tests/rex/+page.svelte

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<script lang="ts">
2+
import type { PageData } from './$types';
3+
import { superForm } from '$lib/client';
4+
import { schema } from './schema';
5+
import { page } from '$app/stores';
6+
7+
export let data: PageData;
8+
9+
// Client API:
10+
const { form, errors, constraints, message, enhance } = superForm(
11+
data.form,
12+
{
13+
validators: schema,
14+
validationMethod: ($page.url.searchParams.get('method') ??
15+
undefined) as any
16+
}
17+
);
18+
</script>
19+
20+
<h4>Validation method: {$page.url.searchParams.get('method') ?? 'auto'}</h4>
21+
22+
<form method="POST" use:enhance>
23+
{#if $message}
24+
<div>Message: {$message}</div>
25+
<br />
26+
{/if}
27+
<label for="name">Name</label>
28+
<input
29+
type="text"
30+
name="name"
31+
data-invalid={$errors.name}
32+
bind:value={$form.name}
33+
/>
34+
<!-- {...$constraints.name} -->
35+
{#if $errors.name}<span class="invalid">{$errors.name}</span>{/if}
36+
37+
<label for="email">E-mail</label>
38+
<input
39+
type="text"
40+
name="email"
41+
data-invalid={$errors.email}
42+
bind:value={$form.email}
43+
/>
44+
<!-- {...$constraints.email} -->
45+
{#if $errors.email}<span class="invalid">{$errors.email}</span>{/if}
46+
47+
<div><button>Submit</button></div>
48+
</form>
49+
50+
<style>
51+
.invalid {
52+
color: red;
53+
}
54+
</style>

src/routes/tests/rex/schema.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { z } from 'zod';
2+
3+
export const schema = z.object({
4+
name: z.string().min(4).default('Hello world!'),
5+
email: z.string().email()
6+
})

0 commit comments

Comments
 (0)