@@ -10,6 +10,7 @@ export class OpenAPIParser {
1010 this . endpoints = new Map ( ) ;
1111 this . schemas = new Map ( ) ;
1212 this . tags = new Map ( ) ;
13+ this . exampleCache = new Map ( ) ; // Cache for generated examples
1314 }
1415
1516 /**
@@ -382,4 +383,195 @@ export class OpenAPIParser {
382383 } ;
383384 return colors [ method ] || 'method-default' ;
384385 }
386+
387+ /**
388+ * Generate example response data from schema
389+ */
390+ generateExampleFromSchema ( schema , depth = 0 , visitedRefs = new Set ( ) ) {
391+ if ( depth > 10 ) return '...' ; // Prevent infinite recursion
392+ if ( ! schema ) return null ;
393+
394+ // Create cache key for this schema at root level only
395+ if ( depth === 0 ) {
396+ const cacheKey = JSON . stringify ( schema ) ;
397+ if ( this . exampleCache . has ( cacheKey ) ) {
398+ return this . exampleCache . get ( cacheKey ) ;
399+ }
400+
401+ // Generate example and cache it
402+ const example = this . _generateExampleFromSchemaInternal ( schema , depth , visitedRefs ) ;
403+ this . exampleCache . set ( cacheKey , example ) ;
404+ return example ;
405+ }
406+
407+ // For nested calls, don't use cache to avoid issues with circular refs
408+ return this . _generateExampleFromSchemaInternal ( schema , depth , visitedRefs ) ;
409+ }
410+
411+ /**
412+ * Internal method for generating examples (without caching)
413+ */
414+ _generateExampleFromSchemaInternal ( schema , depth = 0 , visitedRefs = new Set ( ) ) {
415+ if ( depth > 10 ) return '...' ; // Prevent infinite recursion
416+ if ( ! schema ) return null ;
417+
418+ // Handle schema reference
419+ if ( schema . $ref ) {
420+ const refName = this . resolveRef ( schema . $ref ) ;
421+
422+ if ( ! refName || visitedRefs . has ( refName ) ) {
423+ return `[Reference to ${ refName } ]` ;
424+ }
425+
426+ visitedRefs . add ( refName ) ;
427+ const referencedSchema = this . schemas . get ( refName ) ;
428+
429+ if ( referencedSchema ) {
430+ const result = this . _generateExampleFromSchemaInternal ( referencedSchema , depth + 1 , visitedRefs ) ;
431+ visitedRefs . delete ( refName ) ;
432+ return result ;
433+ }
434+ return `[${ refName } schema not found]` ;
435+ }
436+
437+ // Handle oneOf, anyOf, allOf
438+ if ( schema . oneOf && schema . oneOf . length > 0 ) {
439+ return this . _generateExampleFromSchemaInternal ( schema . oneOf [ 0 ] , depth + 1 , visitedRefs ) ;
440+ }
441+ if ( schema . anyOf && schema . anyOf . length > 0 ) {
442+ return this . _generateExampleFromSchemaInternal ( schema . anyOf [ 0 ] , depth + 1 , visitedRefs ) ;
443+ }
444+ if ( schema . allOf && schema . allOf . length > 0 ) {
445+ // Merge all schemas in allOf
446+ const merged = { } ;
447+ for ( const subSchema of schema . allOf ) {
448+ const example = this . _generateExampleFromSchemaInternal ( subSchema , depth + 1 , visitedRefs ) ;
449+ if ( example && typeof example === 'object' ) {
450+ Object . assign ( merged , example ) ;
451+ }
452+ }
453+ return Object . keys ( merged ) . length > 0 ? merged : null ;
454+ }
455+
456+ // Handle arrays
457+ if ( schema . type === 'array' && schema . items ) {
458+ const itemExample = this . _generateExampleFromSchemaInternal ( schema . items , depth + 1 , visitedRefs ) ;
459+ return [ itemExample ] ;
460+ }
461+
462+ // Handle objects
463+ if ( schema . type === 'object' ) {
464+ const example = { } ;
465+
466+ if ( schema . properties ) {
467+ Object . entries ( schema . properties ) . forEach ( ( [ propName , propSchema ] ) => {
468+ example [ propName ] = this . _generateExampleFromSchemaInternal ( propSchema , depth + 1 , visitedRefs ) ;
469+ } ) ;
470+ }
471+
472+ return example ;
473+ }
474+
475+ // Handle primitive types
476+ return this . generateExampleForPrimitive ( schema ) ;
477+ }
478+
479+ /**
480+ * Generate example for primitive types
481+ */
482+ generateExampleForPrimitive ( schema ) {
483+ const type = schema . type ;
484+ const format = schema . format ;
485+
486+ // Use example if provided
487+ if ( schema . example !== undefined ) {
488+ return schema . example ;
489+ }
490+
491+ // Use enum if available
492+ if ( schema . enum && schema . enum . length > 0 ) {
493+ return schema . enum [ 0 ] ;
494+ }
495+
496+ // Generate based on format
497+ if ( format ) {
498+ switch ( format ) {
499+ case 'SS58' :
500+ return '15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5' ;
501+ case 'unsignedInteger' :
502+ return '1000000000000' ;
503+ case '$hex' :
504+ return '0x1234567890abcdef' ;
505+ case 'date-time' :
506+ return '2023-01-01T12:00:00.000Z' ;
507+ case 'uuid' :
508+ return '123e4567-e89b-12d3-a456-426614174000' ;
509+ case 'email' :
510+ 511+ case 'uri' :
512+ return 'https://example.com' ;
513+ case 'binary' :
514+ return 'base64EncodedData' ;
515+ }
516+ }
517+
518+ // Generate based on type
519+ switch ( type ) {
520+ case 'string' :
521+ if ( schema . description && schema . description . toLowerCase ( ) . includes ( 'hash' ) ) {
522+ return '0x1234567890abcdef1234567890abcdef12345678' ;
523+ }
524+ if ( schema . description && schema . description . toLowerCase ( ) . includes ( 'address' ) ) {
525+ return '15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5' ;
526+ }
527+ return 'example_string' ;
528+ case 'number' :
529+ case 'integer' :
530+ return 123 ;
531+ case 'boolean' :
532+ return true ;
533+ case 'null' :
534+ return null ;
535+ default :
536+ return null ;
537+ }
538+ }
539+
540+ /**
541+ * Generate example response for an endpoint
542+ */
543+ generateExampleResponse ( endpoint , statusCode = '200' ) {
544+ if ( ! endpoint . responses || ! endpoint . responses [ statusCode ] ) {
545+ return null ;
546+ }
547+
548+ const response = endpoint . responses [ statusCode ] ;
549+ const content = response . content ?. [ 'application/json' ] ;
550+
551+ if ( ! content || ! content . schema ) {
552+ return null ;
553+ }
554+
555+ return this . generateExampleFromSchema ( content . schema ) ;
556+ }
557+
558+ /**
559+ * Get all example responses for an endpoint
560+ */
561+ getAllExampleResponses ( endpoint ) {
562+ if ( ! endpoint . responses ) return { } ;
563+
564+ const examples = { } ;
565+ Object . entries ( endpoint . responses ) . forEach ( ( [ statusCode , response ] ) => {
566+ const example = this . generateExampleResponse ( endpoint , statusCode ) ;
567+ if ( example !== null ) {
568+ examples [ statusCode ] = {
569+ description : response . description ,
570+ example : example
571+ } ;
572+ }
573+ } ) ;
574+
575+ return examples ;
576+ }
385577}
0 commit comments