@@ -277,6 +277,13 @@ export default class ScapiSchemasGet extends ScapiSchemasCommand<typeof ScapiSch
277277 return ' (outline only - use --expand-paths, --expand-schemas, or --expand-all for details)' ;
278278 }
279279
280+ /**
281+ * Check if a value is a non-empty object (not an array).
282+ */
283+ private isNonEmptyObject ( value : unknown ) : boolean {
284+ return typeof value === 'object' && value !== null && ! Array . isArray ( value ) && Object . keys ( value ) . length > 0 ;
285+ }
286+
280287 /**
281288 * Output a list of items (paths, schemas, or examples).
282289 */
@@ -302,83 +309,101 @@ export default class ScapiSchemasGet extends ScapiSchemasCommand<typeof ScapiSch
302309 * Uses a simple JSON-to-YAML conversion for basic YAML output.
303310 */
304311 private serializeToYaml ( obj : unknown , indent = 0 ) : string {
305- const indentStr = ' ' . repeat ( indent ) ;
306-
307312 if ( obj === null || obj === undefined ) {
308313 return 'null' ;
309314 }
310315
311316 if ( typeof obj === 'string' ) {
312- // Quote strings that need it
313- if ( obj . includes ( '\n' ) || obj . includes ( ':' ) || obj . includes ( '#' ) || obj === '' ) {
314- return JSON . stringify ( obj ) ;
315- }
316- return obj ;
317+ return this . serializeYamlString ( obj ) ;
317318 }
318319
319320 if ( typeof obj === 'number' || typeof obj === 'boolean' ) {
320321 return String ( obj ) ;
321322 }
322323
323324 if ( Array . isArray ( obj ) ) {
324- if ( obj . length === 0 ) {
325- return '[]' ;
326- }
325+ return this . serializeYamlArray ( obj , indent ) ;
326+ }
327327
328- // For arrays of primitives, use inline format
329- if ( obj . every ( ( item ) => typeof item !== 'object' || item === null ) ) {
330- return `[${ obj . map ( ( item ) => this . serializeToYaml ( item , 0 ) ) . join ( ', ' ) } ]` ;
331- }
328+ if ( typeof obj === 'object' ) {
329+ return this . serializeYamlObject ( obj as Record < string , unknown > , indent ) ;
330+ }
332331
333- // For arrays of objects, use block format
334- const lines : string [ ] = [ ] ;
335- for ( const item of obj ) {
336- const serialized = this . serializeToYaml ( item , indent + 1 ) ;
337- if ( typeof item === 'object' && item !== null && ! Array . isArray ( item ) ) {
338- // Object items - first line starts with -, rest are indented
339- const objLines = serialized . split ( '\n' ) ;
340- lines . push ( `${ indentStr } - ${ objLines [ 0 ] } ` ) ;
341- for ( let i = 1 ; i < objLines . length ; i ++ ) {
342- lines . push ( `${ indentStr } ${ objLines [ i ] } ` ) ;
343- }
344- } else {
345- lines . push ( `${ indentStr } - ${ serialized } ` ) ;
332+ return String ( obj ) ;
333+ }
334+
335+ /**
336+ * Serialize an array to YAML format.
337+ */
338+ private serializeYamlArray ( arr : unknown [ ] , indent : number ) : string {
339+ if ( arr . length === 0 ) {
340+ return '[]' ;
341+ }
342+
343+ // For arrays of primitives, use inline format
344+ if ( arr . every ( ( item ) => typeof item !== 'object' || item === null ) ) {
345+ return `[${ arr . map ( ( item ) => this . serializeToYaml ( item , 0 ) ) . join ( ', ' ) } ]` ;
346+ }
347+
348+ // For arrays of objects, use block format
349+ const indentStr = ' ' . repeat ( indent ) ;
350+ const lines : string [ ] = [ ] ;
351+ for ( const item of arr ) {
352+ const serialized = this . serializeToYaml ( item , indent + 1 ) ;
353+ if ( typeof item === 'object' && item !== null && ! Array . isArray ( item ) ) {
354+ // Object items - first line starts with -, rest are indented
355+ const objLines = serialized . split ( '\n' ) ;
356+ lines . push ( `${ indentStr } - ${ objLines [ 0 ] } ` ) ;
357+ for ( let i = 1 ; i < objLines . length ; i ++ ) {
358+ lines . push ( `${ indentStr } ${ objLines [ i ] } ` ) ;
346359 }
360+ } else {
361+ lines . push ( `${ indentStr } - ${ serialized } ` ) ;
347362 }
348- return lines . join ( '\n' ) ;
349363 }
364+ return lines . join ( '\n' ) ;
365+ }
350366
351- if ( typeof obj === 'object' ) {
352- const entries = Object . entries ( obj as Record < string , unknown > ) ;
353- if ( entries . length === 0 ) {
354- return '{}' ;
355- }
367+ /**
368+ * Serialize an object to YAML format.
369+ */
370+ private serializeYamlObject ( obj : Record < string , unknown > , indent : number ) : string {
371+ const entries = Object . entries ( obj ) ;
372+ if ( entries . length === 0 ) {
373+ return '{}' ;
374+ }
356375
357- const lines : string [ ] = [ ] ;
358- for ( const [ key , value ] of entries ) {
359- const serializedValue = this . serializeToYaml ( value , indent + 1 ) ;
360- if ( typeof value === 'object' && value !== null && ! Array . isArray ( value ) && Object . keys ( value ) . length > 0 ) {
361- // Nested object - put on next line
362- lines . push ( `${ indentStr } ${ key } :` ) ;
363- const valueLines = serializedValue . split ( '\n' ) ;
364- for ( const line of valueLines ) {
365- lines . push ( `${ indentStr } ${ line } ` ) ;
366- }
367- } else if ( Array . isArray ( value ) && value . some ( ( item ) => typeof item === 'object' ) ) {
368- // Array with objects - put on next line
369- lines . push ( `${ indentStr } ${ key } :` ) ;
370- const valueLines = serializedValue . split ( '\n' ) ;
371- for ( const line of valueLines ) {
372- lines . push ( line ) ;
373- }
374- } else {
375- // Simple value or empty object/array - inline
376- lines . push ( `${ indentStr } ${ key } : ${ serializedValue } ` ) ;
376+ const indentStr = ' ' . repeat ( indent ) ;
377+ const lines : string [ ] = [ ] ;
378+ for ( const [ key , value ] of entries ) {
379+ const serializedValue = this . serializeToYaml ( value , indent + 1 ) ;
380+ if ( this . isNonEmptyObject ( value ) ) {
381+ // Nested object - put on next line
382+ lines . push ( `${ indentStr } ${ key } :` ) ;
383+ for ( const line of serializedValue . split ( '\n' ) ) {
384+ lines . push ( `${ indentStr } ${ line } ` ) ;
377385 }
386+ } else if ( Array . isArray ( value ) && value . some ( ( item ) => typeof item === 'object' ) ) {
387+ // Array with objects - put on next line
388+ lines . push ( `${ indentStr } ${ key } :` ) ;
389+ for ( const line of serializedValue . split ( '\n' ) ) {
390+ lines . push ( line ) ;
391+ }
392+ } else {
393+ // Simple value or empty object/array - inline
394+ lines . push ( `${ indentStr } ${ key } : ${ serializedValue } ` ) ;
378395 }
379- return lines . join ( '\n' ) ;
380396 }
397+ return lines . join ( '\n' ) ;
398+ }
381399
382- return String ( obj ) ;
400+ /**
401+ * Serialize a string value to YAML, quoting if necessary.
402+ */
403+ private serializeYamlString ( str : string ) : string {
404+ if ( str . includes ( '\n' ) || str . includes ( ':' ) || str . includes ( '#' ) || str === '' ) {
405+ return JSON . stringify ( str ) ;
406+ }
407+ return str ;
383408 }
384409}
0 commit comments