Skip to content

Commit 0289a8b

Browse files
committed
All properties for object unions weren't added to the adapter defaults.
Fixes #519
1 parent f2201d1 commit 0289a8b

File tree

3 files changed

+69
-3
lines changed

3 files changed

+69
-3
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+
## [Unreleased]
9+
10+
### Fixed
11+
12+
- All properties for object unions weren't added to the adapter defaults.
13+
814
## [2.20.1] - 2024-11-15
915

1016
### Changed

src/lib/jsonSchema/schemaDefaults.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ function _defaultValues(schema: JSONSchema, isOptional: boolean, path: string[])
7070
return _multiType.size > 1;
7171
};
7272

73-
let output: Record<string, unknown> = {};
73+
let output: Record<string, unknown> | undefined = undefined;
7474

7575
// Check unions first, so default values can take precedence over nullable and optional
7676
if (!objectDefaults && info.union) {
@@ -98,6 +98,7 @@ function _defaultValues(schema: JSONSchema, isOptional: boolean, path: string[])
9898

9999
// Objects must have default values to avoid setting undefined properties on nested data
100100
if (info.union.length && info.types[0] == 'object') {
101+
if (output === undefined) output = {};
101102
output =
102103
info.union.length > 1
103104
? merge.withOptions(
@@ -128,9 +129,9 @@ function _defaultValues(schema: JSONSchema, isOptional: boolean, path: string[])
128129
: _defaultValues(objSchema, !info.required?.includes(key), [...path, key]);
129130

130131
//if (def !== undefined) output[key] = def;
132+
if (output === undefined) output = {};
131133
output[key] = def;
132134
}
133-
return output;
134135
} else if (objectDefaults) {
135136
return objectDefaults;
136137
}
@@ -159,7 +160,7 @@ function _defaultValues(schema: JSONSchema, isOptional: boolean, path: string[])
159160

160161
const [formatType] = info.types;
161162

162-
return defaultValue(formatType, schema.enum);
163+
return output ?? defaultValue(formatType, schema.enum);
163164
}
164165

165166
function formatDefaultValue(type: SchemaType, value: unknown) {

src/tests/zodUnion.test.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { zod } from '$lib/adapters/zod.js';
2+
import { superValidate } from '$lib/superValidate.js';
3+
import { stringify } from 'devalue';
4+
import { describe, test } from 'vitest';
5+
import { z } from 'zod';
6+
7+
const ZodSchema = z.object({
8+
addresses: z.object({
9+
additional: z.discriminatedUnion('type', [
10+
z.object({
11+
type: z.literal('poBox'),
12+
name: z.string().min(1, 'min len').max(10, 'max len')
13+
}),
14+
z.object({
15+
type: z.literal('none')
16+
})
17+
])
18+
})
19+
});
20+
const FormSchema = zod(ZodSchema);
21+
type FormSchema = (typeof FormSchema)['defaults'];
22+
23+
async function validate(data: unknown) {
24+
const formInput = new FormData();
25+
26+
formInput.set('__superform_json', stringify(data));
27+
try {
28+
await superValidate(formInput, FormSchema);
29+
} catch (err) {
30+
console.error(err);
31+
//
32+
throw err;
33+
}
34+
}
35+
36+
describe('Demo', () => {
37+
test('Bad', async () => {
38+
const data = {
39+
addresses: {
40+
additional: {
41+
type: 'poBox',
42+
name: ''
43+
}
44+
}
45+
} satisfies FormSchema;
46+
await validate(data);
47+
});
48+
49+
test('Good', async () => {
50+
const data = {
51+
addresses: {
52+
additional: {
53+
type: 'none'
54+
}
55+
}
56+
} satisfies FormSchema;
57+
await validate(data);
58+
});
59+
});

0 commit comments

Comments
 (0)