Skip to content

Commit 763b524

Browse files
committed
Nullable fields weren't always detected in JSON Schemas.
1 parent e60dd35 commit 763b524

File tree

6 files changed

+117
-3
lines changed

6 files changed

+117
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313

1414
### Fixed
1515

16+
- Nullable fields weren't always detected in JSON Schemas.
1617
- Constraints weren't added when using default values for an adapter with introspection.
1718

1819
## [2.3.0] - 2024-02-18

src/lib/jsonSchema/schemaInfo.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ export type SchemaInfo = {
2626

2727
const conversionFormatTypes = ['unix-time', 'bigint', 'any', 'symbol', 'set'];
2828

29+
/**
30+
* Normalizes the different kind of schema variations (anyOf, union, const null, etc)
31+
* to figure out the field type, optional, nullable, etc.
32+
*/
2933
export function schemaInfo(
3034
schema: JSONSchema7Definition,
3135
isOptional: boolean,
@@ -53,7 +57,7 @@ export function schemaInfo(
5357
) as { [key: string]: JSONSchema7 })
5458
: undefined;
5559

56-
const union = unionInfo(schema)?.filter((u) => u.type !== 'null');
60+
const union = unionInfo(schema)?.filter((u) => u.type !== 'null' && u.const !== null);
5761

5862
return {
5963
types: types.filter((s) => s !== 'null') as SchemaInfo['types'],
@@ -75,7 +79,7 @@ function schemaTypes(
7579
throw new SchemaError('Schema cannot be defined as boolean', path);
7680
}
7781

78-
let types: SchemaType[] = [];
82+
let types: SchemaType[] = schema.const === null ? ['null'] : [];
7983

8084
if (schema.type) {
8185
types = Array.isArray(schema.type) ? schema.type : [schema.type];

src/routes/(v2)/v2/Navigation.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@
2929
'trim-fields',
3030
'unions',
3131
'valibot-dates',
32+
'valibot-nullable',
3233
'validate',
3334
'validate-update',
3435
'validators-clear'
35-
];
36+
].sort();
3637
</script>
3738

3839
<nav class="flex-list">
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { superValidate, message } from '$lib/index.js';
2+
import { valibot } from '$lib/adapters/valibot.js';
3+
import { fail } from '@sveltejs/kit';
4+
import { schema } from './schema.js';
5+
6+
export const load = async () => {
7+
const form = await superValidate(valibot(schema));
8+
return { form };
9+
};
10+
11+
export const actions = {
12+
default: async ({ request }) => {
13+
const form = await superValidate(request, valibot(schema));
14+
console.log(form);
15+
16+
if (!form.valid) return fail(400, { form });
17+
18+
return message(form, 'Form posted successfully!');
19+
}
20+
};
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<script lang="ts">
2+
import { page } from '$app/stores';
3+
import { superForm } from '$lib/index.js';
4+
import SuperDebug from '$lib/index.js';
5+
6+
export let data;
7+
8+
const { form, errors, message, enhance } = superForm(data.form);
9+
</script>
10+
11+
<SuperDebug data={$form} />
12+
13+
<h3>Nullable Valibot schema</h3>
14+
15+
{#if $message}
16+
<div class="status" class:error={$page.status >= 400} class:success={$page.status == 200}>
17+
{$message}
18+
</div>
19+
{/if}
20+
21+
<form method="POST" use:enhance>
22+
<label>
23+
Name<br />
24+
<input name="name" aria-invalid={$errors.name ? 'true' : undefined} bind:value={$form.name} />
25+
{#if $errors.name}<span class="invalid">{$errors.name}</span>{/if}
26+
</label>
27+
28+
<label>
29+
Email<br />
30+
<input
31+
name="email"
32+
type="email"
33+
aria-invalid={$errors.email ? 'true' : undefined}
34+
bind:value={$form.email}
35+
/>
36+
{#if $errors.email}<span class="invalid">{$errors.email}</span>{/if}
37+
</label>
38+
39+
<button>Submit</button>
40+
</form>
41+
42+
<hr />
43+
<p><a target="_blank" href="https://superforms.rocks/api">API Reference</a></p>
44+
45+
<style>
46+
.invalid {
47+
color: red;
48+
}
49+
50+
.status {
51+
color: white;
52+
padding: 4px;
53+
padding-left: 8px;
54+
border-radius: 2px;
55+
font-weight: 500;
56+
}
57+
58+
.status.success {
59+
background-color: seagreen;
60+
}
61+
62+
.status.error {
63+
background-color: #ff2a02;
64+
}
65+
66+
input {
67+
background-color: #ddd;
68+
}
69+
70+
a {
71+
text-decoration: underline;
72+
}
73+
74+
hr {
75+
margin-top: 4rem;
76+
}
77+
78+
form {
79+
padding-top: 1rem;
80+
padding-bottom: 1rem;
81+
}
82+
</style>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { object, string, minLength, email, nullable } from 'valibot';
2+
3+
export const schema = object({
4+
name: nullable(string([minLength(1)])),
5+
email: string([email()])
6+
});

0 commit comments

Comments
 (0)