Skip to content

Commit 4a430e4

Browse files
fix(zui): x-zui properties on optional not handled by zui-from-json-schema-legacy transformer (#639)
Co-authored-by: François Levasseur <francois_levasseur@hotmail.com> Co-authored-by: Xavier Hamel <xavier.hamel@botpress.com>
1 parent 92de012 commit 4a430e4

File tree

3 files changed

+26
-5
lines changed

3 files changed

+26
-5
lines changed

zui/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@bpinternal/zui",
3-
"version": "1.1.0",
3+
"version": "1.1.1",
44
"description": "A fork of Zod with additional features",
55
"type": "module",
66
"source": "./src/index.ts",
@@ -55,4 +55,4 @@
5555
"pnpm": "8.6.2"
5656
},
5757
"packageManager": "pnpm@8.6.2"
58-
}
58+
}

zui/src/transforms/zui-from-json-schema-legacy/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const jsonSchemaToZod = (schema: any): ZodTypeAny => {
4646

4747
const applyZuiPropsRecursively = (zodField: ZodTypeAny, jsonSchemaField: any) => {
4848
if (jsonSchemaField[zuiKey] && zodField._def) {
49-
zodField._def[zuiKey] = jsonSchemaField[zuiKey]
49+
zodField.naked()._def[zuiKey] = jsonSchemaField[zuiKey]
5050
}
5151

5252
if (zodField._def?.typeName === 'ZodObject' && jsonSchemaField.type === 'object' && jsonSchemaField.properties) {

zui/src/transforms/zui-from-json-schema-legacy/json-schema-to-zui.test.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,27 @@ describe('jsonSchemaToZui', () => {
9797
expect(jsonSchema).toEqual(converted)
9898
})
9999

100+
test('should map extensions (x-zui) to zod schema for ZodOptional', () => {
101+
const jSchema = {
102+
type: 'object',
103+
properties: {
104+
optional: {
105+
type: 'string',
106+
'x-zui': {
107+
secret: true,
108+
},
109+
},
110+
},
111+
} as JSONSchema7
112+
const zSchema = fromJSONSchemaLegacy(jSchema)
113+
const expected = z.object({
114+
optional: z.optional(z.string().secret()),
115+
})
116+
expect(zSchema.isEqual(expected)).toBe(true)
117+
const field = (zSchema as z.ZodObject)._def.shape().optional as z.ZodOptional<z.ZodString>
118+
expect(field._def.innerType._def['x-zui']?.secret, 'Expected secret to be true').toBe(true)
119+
})
120+
100121
test('convert object with nested', () => {
101122
const zuiSchema = fromJSONSchemaLegacy({
102123
type: 'object',
@@ -136,8 +157,8 @@ describe('jsonSchemaToZui', () => {
136157
traverseZodDefinitions(zuiSchema._def, (type, def, path) => {
137158
if (path.join('.') === 'address.city.bestFoods') {
138159
expect(['ZodArray', 'ZodOptional']).toContain(type)
139-
if (type === 'ZodOptional') {
140-
expect(def[zuiKey]?.title).toBe('Best foods')
160+
if (def.typeName === 'ZodOptional') {
161+
expect(def.innerType._def[zuiKey]?.title).toBe('Best foods')
141162
}
142163
}
143164
if (path.join('.') === 'address.city.bestFoods.0.type') {

0 commit comments

Comments
 (0)