Clean up parse output and schema enumerability

Skip assigning undefined keys for absent optional fields in parse,
matching the previous zod-object behavior. Make the schema getter
non-enumerable so JSON.stringify on the portable schema only
serializes parse and _fields.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
This commit is contained in:
Patrik Oldsberg
2026-04-10 15:09:02 +02:00
parent 27f6fb30e7
commit 461d4fc48b
9 changed files with 14 additions and 9 deletions
@@ -190,7 +190,6 @@ describe('ApiBlueprint', () => {
},
},
"parse": [Function],
"schema": [Function],
},
"disabled": false,
"factory": [Function],
@@ -47,7 +47,6 @@ describe('NavItemBlueprint', () => {
},
},
"parse": [Function],
"schema": [Function],
},
"disabled": false,
"factory": [Function],
@@ -61,7 +61,6 @@ describe('PageBlueprint', () => {
},
},
"parse": [Function],
"schema": [Function],
},
"disabled": false,
"factory": [Function],
@@ -367,6 +367,18 @@ describe('createConfigSchema', () => {
);
});
it('should not produce undefined keys for absent optional fields', () => {
const schema = createConfigSchema({
name: z => z.string(),
title: z => z.string().optional(),
count: z => z.number().default(42),
});
const result = schema.parse({ name: 'hello' });
expect(result).toEqual({ name: 'hello', count: 42 });
expect(Object.keys(result as object)).toEqual(['name', 'count']);
});
it('should not mark defaulted zod v3 fields as required in JSON Schema', () => {
const schema = createConfigSchema({
name: z => z.string(),
@@ -119,7 +119,7 @@ function buildPortableSchema<TOutput = unknown>(
const validated = field.validate(inputObj[key]);
if ('errors' in validated) {
errors.push(...validated.errors);
} else {
} else if (validated.value !== undefined || key in inputObj) {
result[key] = validated.value;
}
}
@@ -152,7 +152,7 @@ function buildPortableSchema<TOutput = unknown>(
return cached;
},
configurable: true,
enumerable: true,
enumerable: false,
});
return result;
@@ -58,7 +58,6 @@ describe('EntityCardBlueprint', () => {
},
},
"parse": [Function],
"schema": [Function],
},
"disabled": false,
"factory": [Function],
@@ -75,7 +75,6 @@ describe('EntityContentBlueprint', () => {
},
},
"parse": [Function],
"schema": [Function],
},
"disabled": false,
"factory": [Function],
@@ -71,7 +71,6 @@ describe('EntityContextMenuItemBlueprint', () => {
},
},
"parse": [Function],
"schema": [Function],
},
"disabled": false,
"factory": [Function],
@@ -53,7 +53,6 @@ describe('SearchResultListItemBlueprint', () => {
},
},
"parse": [Function],
"schema": [Function],
},
"disabled": false,
"factory": [Function],