Skip to content

Commit

Permalink
feat(zui): map json schema references to zui refs (#386)
Browse files Browse the repository at this point in the history
  • Loading branch information
franklevasseur authored Oct 1, 2024
1 parent ee04385 commit a0143c2
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 2 deletions.
3 changes: 2 additions & 1 deletion zui/src/transforms/json-schema-to-zui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ import { zuiKey } from '../../ui/constants'
import { JsonSchema7Type } from '../zui-to-json-schema/parseDef'
import { parseSchema } from './parsers/parseSchema'
import { ZuiExtensionObject } from '../../ui/types'
import { JSONSchemaExtended } from './types'

const jsonSchemaToZodStr = (schema: any): string => {
export const jsonSchemaToZodStr = (schema: JSONSchemaExtended): string => {
return parseSchema(schema, {
seen: new Map(),
path: [],
Expand Down
43 changes: 42 additions & 1 deletion zui/src/transforms/json-schema-to-zui/json-schema-to-zui.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { describe, expect, test } from 'vitest'
import { ZodTypeAny, z } from '../../z/index'
import { zuiKey } from '../../ui/constants'
import { jsonSchemaToZui, traverseZodDefinitions } from '.'
import { jsonSchemaToZodStr, jsonSchemaToZui, traverseZodDefinitions } from '.'
import { zuiToJsonSchema } from '../zui-to-json-schema/zui-extension'
import { JSONSchema7 } from 'json-schema'

const testZuiConversion = (zuiObject: ZodTypeAny) => {
const jsonSchema = zuiToJsonSchema(zuiObject)
Expand Down Expand Up @@ -177,4 +178,44 @@ describe('Coercion deserialization', () => {
const asZui = jsonSchemaToZui(schema)
expect(asZui._def[zuiKey]?.coerce).toStrictEqual(true)
})

it('should convert unresolved refs to zod refs', async () => {
const schema: JSONSchema7 = {
type: 'object',
properties: {
foo: { $ref: '#Foo' },
},
required: ['foo'],
}
const zStr = jsonSchemaToZodStr(schema)
await expect(zStr).toMatchWithoutFormatting(`
z.object({ foo: z.ref("#Foo") })
`)
})

// TODO: decide if we want to support dereferencing; if not, remove this test, otherwise fix it
it.skip('should resolve local refs', async () => {
const schema: JSONSchema7 = {
$defs: {
Foo: {
type: 'string',
enum: ['foo'],
},
Bar: {
type: 'string',
enum: ['bar'],
},
},
type: 'object',
properties: {
foo: { $ref: '#/$defs/Foo' },
bar: { $ref: '#/$defs/Bar' },
},
required: ['foo', 'bar'],
}
const zStr = jsonSchemaToZodStr(schema)
await expect(zStr).toMatchWithoutFormatting(`
z.object({ foo: z.literal("foo"), bar: z.literal("bar") })
`)
})
})
5 changes: 5 additions & 0 deletions zui/src/transforms/json-schema-to-zui/parsers/parseRef.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { JsonSchemaObject } from '../types'

export const parseRef = (schema: JsonSchemaObject & { $ref: string }) => {
return `z.ref('${schema.$ref}')`
}
4 changes: 4 additions & 0 deletions zui/src/transforms/json-schema-to-zui/parsers/parseSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { parseObject } from './parseObject'
import { parseString } from './parseString'
import { parseOneOf } from './parseOneOf'
import { parseNullable } from './parseNullable'
import { parseRef } from './parseRef'
import { ParserSelector, Refs, JsonSchemaObject, JsonSchema, Serializable, JSONSchemaExtended } from '../types'
import { parseDiscriminator } from './parseDiscriminator'

Expand Down Expand Up @@ -113,6 +114,8 @@ const selectParser: ParserSelector = (schema, refs) => {
return parseNull(schema)
} else if (its.a.conditional(schema)) {
return parseIfThenElse(schema, refs)
} else if (its.a.ref(schema)) {
return parseRef(schema)
} else {
return parseDefault(schema)
}
Expand Down Expand Up @@ -173,5 +176,6 @@ export const its = {
): x is JsonSchemaObject & {
oneOf: JsonSchema[]
} => x.oneOf !== undefined,
ref: (x: JsonSchemaObject): x is JsonSchemaObject & { $ref: string } => x.$ref !== undefined,
},
}

0 comments on commit a0143c2

Please sign in to comment.