@@ -77,10 +77,19 @@ export function extractRequestBodyFromDiscovery(
7777
7878 if ( jsonContent . example ) return JSON . stringify ( jsonContent . example )
7979
80- const schema = jsonContent . schema as Record < string , unknown > | undefined
80+ if ( jsonContent . examples && typeof jsonContent . examples === 'object' ) {
81+ const first = Object . values ( jsonContent . examples as Record < string , unknown > ) [ 0 ] as
82+ | Record < string , unknown >
83+ | undefined
84+ if ( first ?. value ) return JSON . stringify ( first . value )
85+ }
86+
87+ let schema = jsonContent . schema as Record < string , unknown > | undefined
88+ const seen = new Set < string > ( )
89+ schema = resolveRef ( schema , doc , seen )
8190 if ( ! schema || schema . type !== 'object' ) return undefined
8291
83- const result = generateValueFromSchema ( schema )
92+ const result = generateValueFromSchema ( schema , doc , seen )
8493 if ( result && typeof result === 'object' && Object . keys ( result as object ) . length > 0 ) {
8594 return JSON . stringify ( result )
8695 }
@@ -149,34 +158,60 @@ function substitutePathParams(path: string, params: PathParameter[]): string {
149158 } )
150159}
151160
152- function generateValueFromSchema ( schema : Record < string , unknown > ) : unknown {
153- if ( schema . const !== undefined ) return schema . const
154- if ( schema . example !== undefined ) return schema . example
155- if ( schema . default !== undefined ) return schema . default
161+ // Dereferences a JSON Schema $ref (e.g. "#/components/schemas/Foo") against the root doc.
162+ function resolveRef (
163+ schema : Record < string , unknown > | undefined ,
164+ doc : Record < string , unknown > ,
165+ seen ?: Set < string > ,
166+ ) : Record < string , unknown > | undefined {
167+ if ( ! schema || typeof schema . $ref !== 'string' ) return schema
168+ if ( seen ?. has ( schema . $ref ) ) return undefined
169+ const path = schema . $ref . replace ( / ^ # \/ / , '' ) . split ( '/' )
170+ let resolved : unknown = doc
171+ for ( const segment of path ) {
172+ if ( resolved && typeof resolved === 'object' ) resolved = ( resolved as any ) [ segment ]
173+ else return undefined
174+ }
175+ return resolved as Record < string , unknown > | undefined
176+ }
156177
157- switch ( schema . type ) {
178+ // Generates a plausible value for a JSON Schema node (required fields only for objects).
179+ function generateValueFromSchema (
180+ schema : Record < string , unknown > ,
181+ doc : Record < string , unknown > ,
182+ seen ?: Set < string > ,
183+ ) : unknown {
184+ const resolved = resolveRef ( schema , doc , seen ) ?? schema
185+ if ( resolved . const !== undefined ) return resolved . const
186+ if ( resolved . example !== undefined ) return resolved . example
187+ if ( resolved . default !== undefined ) return resolved . default
188+
189+ switch ( resolved . type ) {
158190 case 'string' : {
159- if ( schema . enum && Array . isArray ( schema . enum ) ) return schema . enum [ 0 ]
160- if ( schema . format === 'email' ) return 'test@example.com'
161- if ( schema . format === 'uuid' ) return '00000000-0000-0000-0000-000000000000'
162- if ( schema . format === 'uri' || schema . format === 'url' ) return 'https://example.com'
191+ if ( resolved . enum && Array . isArray ( resolved . enum ) ) return resolved . enum [ 0 ]
192+ if ( resolved . format === 'email' ) return 'test@example.com'
193+ if ( resolved . format === 'uuid' ) return '00000000-0000-0000-0000-000000000000'
194+ if ( resolved . format === 'uri' || resolved . format === 'url' ) return 'https://example.com'
195+ if ( resolved . format === 'date' ) return '2026-01-01'
196+ if ( resolved . pattern === '^\\d{5}(?:-\\d{4})?$' ) return '10001'
197+ if ( resolved . pattern === '^[A-Z]{2}$' ) return 'US'
163198 return 'test'
164199 }
165200 case 'number' :
166201 case 'integer' :
167- return ( schema . minimum as number ) ?? 1
202+ return ( resolved . minimum as number ) ?? 1
168203 case 'boolean' :
169204 return true
170205 case 'array' :
171206 return [ ]
172207 case 'object' : {
173- const properties = schema . properties as Record < string , Record < string , unknown > > | undefined
208+ const properties = resolved . properties as Record < string , Record < string , unknown > > | undefined
174209 if ( ! properties ) return { }
175- const required = ( schema . required as string [ ] ) || [ ]
210+ const required = ( resolved . required as string [ ] ) || [ ]
176211 const obj : Record < string , unknown > = { }
177212 for ( const key of required ) {
178213 const prop = properties [ key ]
179- if ( prop ) obj [ key ] = generateValueFromSchema ( prop )
214+ if ( prop ) obj [ key ] = generateValueFromSchema ( prop , doc , seen )
180215 }
181216 return obj
182217 }
0 commit comments