Skip to content

Commit 7f948c0

Browse files
committed
Fixed default properties for Record in schemas.
1 parent 1fd7296 commit 7f948c0

File tree

3 files changed

+42
-15
lines changed

3 files changed

+42
-15
lines changed

src/lib/jsonSchema/schemaDefaults.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,20 @@ function _defaultTypes(schema: JSONSchema, isOptional: boolean, path: string[])
260260
}
261261
}
262262

263+
// Check if a Record type is used for additionalProperties
264+
if (info.additionalProperties && info.types.includes('object')) {
265+
const additionalInfo = schemaInfo(info.additionalProperties, info.isOptional, path);
266+
if (additionalInfo.properties && additionalInfo.types.includes('object')) {
267+
for (const [key] of Object.entries(additionalInfo.properties)) {
268+
output[key] = _defaultTypes(
269+
additionalInfo.properties[key],
270+
!additionalInfo.required?.includes(key),
271+
[...path, key]
272+
);
273+
}
274+
}
275+
}
276+
263277
if (info.isNullable && !output.__types.includes('null')) {
264278
output.__types.push('null');
265279
}

src/lib/jsonSchema/schemaInfo.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export type SchemaInfo = {
2222
union?: JSONSchema7[];
2323
array?: JSONSchema7[];
2424
properties?: { [key: string]: JSONSchema7 };
25+
additionalProperties?: { [key: string]: JSONSchema7 };
2526
required?: string[];
2627
};
2728

@@ -58,19 +59,22 @@ export function schemaInfo(
5859
: undefined;
5960

6061
const additionalProperties =
61-
types.includes('object') && typeof schema.additionalProperties == 'object'
62-
? schemaInfo(schema.additionalProperties, isOptional, path)
62+
schema.additionalProperties &&
63+
typeof schema.additionalProperties === 'object' &&
64+
types.includes('object')
65+
? (Object.fromEntries(
66+
Object.entries(schema.additionalProperties).filter(
67+
([, value]) => typeof value !== 'boolean'
68+
)
69+
) as { [key: string]: JSONSchema7 })
6370
: undefined;
6471

65-
const mergedProperties = types.includes('object')
66-
? { ...additionalProperties?.properties, ...schema.properties }
67-
: undefined;
68-
69-
const properties = mergedProperties
70-
? (Object.fromEntries(
71-
Object.entries(mergedProperties).filter(([, value]) => typeof value !== 'boolean')
72-
) as { [key: string]: JSONSchema7 })
73-
: undefined;
72+
const properties =
73+
schema.properties && types.includes('object')
74+
? (Object.fromEntries(
75+
Object.entries(schema.properties).filter(([, value]) => typeof value !== 'boolean')
76+
) as { [key: string]: JSONSchema7 })
77+
: undefined;
7478

7579
const union = unionInfo(schema)?.filter((u) => u.type !== 'null' && u.const !== null);
7680

@@ -82,6 +86,7 @@ export function schemaInfo(
8286
union: union?.length ? union : undefined,
8387
array,
8488
properties,
89+
additionalProperties,
8590
required: schema.required
8691
};
8792
}

src/tests/superValidate.test.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ describe('Zod', () => {
628628
expect(() => zod(schema)).toThrow(Error);
629629
});
630630

631-
describe.only('with z.record', () => {
631+
describe('with z.record', () => {
632632
it('should work with additionalProperties for records', async () => {
633633
/*
634634
{
@@ -662,7 +662,7 @@ describe('Zod', () => {
662662
)
663663
});
664664

665-
let row = {
665+
const row = {
666666
id: '1',
667667
options: {
668668
'1': {
@@ -674,8 +674,16 @@ describe('Zod', () => {
674674
}
675675
};
676676

677-
const form = await superValidate(row, zod(schema));
678-
console.dir(form, { depth: 10 }); //debug
677+
const adapter = zod(schema);
678+
const form = await superValidate(row, adapter);
679+
680+
assert(!form.valid);
681+
682+
expect(form.errors).toStrictEqual({
683+
options: { '2': { label: ['Label is required'] } }
684+
});
685+
686+
expect(form.data).toEqual(row);
679687
});
680688
});
681689

0 commit comments

Comments
 (0)