@@ -48,13 +48,13 @@ const _generateSchemaFile = (opts: { schema: z.ZodObject<any>; schemaId: string;
4848 const jsonSchema : any = zodToJsonSchema ( schema ) ;
4949 jsonSchema [ '$schema' ] = 'http://json-schema.org/draft-04/schema#' ;
5050
51+ const resolvedSchema = resolveRefsInSchema ( { ...jsonSchema } ) ;
5152 const destFolder = path . join ( ctx . paths . project . dir , `docs/api/schemas` ) ;
5253 if ( ! fs . existsSync ( destFolder ) ) {
5354 fs . mkdirSync ( destFolder , { recursive : true } ) ;
5455 }
5556 const destPath = path . join ( destFolder , `${ schemaId } .md` ) ;
56- // console.log(generate(jsonSchema));
57- fs . writeFileSync ( destPath , generate ( jsonSchema , schemaId , sideBarTitle ) ) ;
57+ fs . writeFileSync ( destPath , generate ( resolvedSchema , schemaId , sideBarTitle ) ) ;
5858} ;
5959
6060const generateElementTitle = (
@@ -135,11 +135,17 @@ const generateSchemaSectionText = (
135135
136136 if ( schemaType === 'object' ) {
137137 if ( schema . properties ) {
138- text . push ( 'Properties of the `' + name + '` object:' ) ;
138+ text . push ( 'Properties of the' + ( name ? ' `' + name + '`' : '' ) + ' object:') ;
139139 generatePropertySection ( hashtags , schema , subSchemas ) . forEach ( ( section ) => {
140140 text = text . concat ( section ) ;
141141 } ) ;
142142 }
143+ if ( schema . additionalProperties . properties ) {
144+ text . push ( 'Properties of the' + ( name ? ' `' + name + '`' : '' ) + ' object:' ) ;
145+ generatePropertySection ( hashtags , schema . additionalProperties , subSchemas ) . forEach ( ( section ) => {
146+ text = text . concat ( section ) ;
147+ } ) ;
148+ }
143149 } else if ( schemaType === 'array' ) {
144150 let itemsType = schema . items && schema . items . type ;
145151
@@ -170,7 +176,7 @@ const generateSchemaSectionText = (
170176
171177 if ( validationItems . length > 0 ) {
172178 validationItems . forEach ( ( item : any ) => {
173- text = text . concat ( generateSchemaSectionText ( hashtags , item . title , false , item , subSchemas ) ) ;
179+ text = text . concat ( generateSchemaSectionText ( hashtags , item . title || '' , false , item , subSchemas ) ) ;
174180 } ) ;
175181 }
176182 }
@@ -288,28 +294,58 @@ sidebar_label: ${sidebarLabel}
288294 } else {
289295 text = text . concat ( generateSchemaSectionText ( '#' + hashtags , undefined , false , schema , subSchemaTypes ) ) ;
290296 }
291-
292- if ( schema . definitions ) {
293- text . push ( '---' ) ;
294- text . push ( '# Sub Schemas' ) ;
295- text . push ( 'The schema defines the following additional types:' ) ;
296- Object . keys ( schema . definitions ) . forEach ( ( subSchemaTypeName ) => {
297- text . push ( '## `' + subSchemaTypeName + '` (' + schema . definitions [ subSchemaTypeName ] . type + ')' ) ;
298- text . push ( schema . definitions [ subSchemaTypeName ] . description ) ;
299- if ( schema . definitions [ subSchemaTypeName ] . type === 'object' ) {
300- if ( schema . definitions [ subSchemaTypeName ] . properties ) {
301- text . push ( 'Properties of the `' + subSchemaTypeName + '` object:' ) ;
302- }
303- }
304- generatePropertySection ( '##' , schema . definitions [ subSchemaTypeName ] , subSchemaTypes ) . forEach ( ( section ) => {
305- text = text . concat ( section ) ;
306- } ) ;
307- } ) ;
308- }
309-
310297 return text
311298 . filter ( ( line ) => {
312299 return ! ! line ;
313300 } )
314301 . join ( '\n\n' ) ;
315302} ;
303+
304+ const resolveRefsInSchema = ( schema : any ) : any => {
305+ const resolveJsonRefs = ( schema : any , ref : string ) : any => {
306+ const pointer = ref . replace ( / ^ # \/ / , '' ) . split ( '/' ) ;
307+ return pointer . reduce ( ( acc , key ) => acc && acc [ key ] , schema ) ;
308+ } ;
309+
310+ const resolveRefs = ( currentSchema : any , depth = 0 ) : any => {
311+ if ( currentSchema . $ref ) {
312+ const resolvedSchema = resolveJsonRefs ( schema , currentSchema . $ref ) ;
313+
314+ return resolveRefs ( resolvedSchema , depth ) ;
315+ }
316+
317+ if ( currentSchema . type === 'object' && currentSchema . properties ) {
318+ const newProperties = { } ;
319+ Object . keys ( currentSchema . properties ) . forEach ( ( key ) => {
320+ newProperties [ key ] = resolveRefs ( currentSchema . properties [ key ] , depth ) ;
321+ } ) ;
322+ return { ...currentSchema , properties : newProperties } ;
323+ }
324+
325+ if ( currentSchema . additionalProperties && typeof currentSchema . additionalProperties === 'object' ) {
326+ const resolvedAdditionalProperties = resolveRefs ( currentSchema . additionalProperties , depth ) ;
327+ return { ...currentSchema , additionalProperties : resolvedAdditionalProperties } ;
328+ }
329+
330+ if ( currentSchema . type === 'array' && currentSchema . items ) {
331+ if ( depth > 0 ) {
332+ return currentSchema ;
333+ }
334+ // depth <= recursion limit for `items` field to avoid circular refs (children)
335+ const resolvedItems = resolveRefs ( currentSchema . items , depth + 1 ) ;
336+
337+ return { ...currentSchema , items : resolvedItems } ;
338+ }
339+ if ( Array . isArray ( currentSchema . anyOf ) ) {
340+ return {
341+ ...currentSchema ,
342+ anyOf : currentSchema . anyOf . map ( ( subSchema : any ) => {
343+ return resolveRefs ( subSchema , depth ) ;
344+ } ) ,
345+ } ;
346+ }
347+ return currentSchema ;
348+ } ;
349+
350+ return resolveRefs ( schema ) ;
351+ } ;
0 commit comments