@@ -227,10 +227,19 @@ export class DynamicTypeLiteralMapper {
227227 if ( named == null ) {
228228 return undefined ;
229229 }
230- const converted = this . convertNamed ( { named, value : discriminatedUnionTypeInstance . value } ) ;
231- // For Ruby, we expect a hash back from convertNamed for objects
232- // We need to extract the entries from the hash
233- return this . extractHashEntries ( converted ) ;
230+ // For samePropertiesAsObject, the named type should be an object
231+ // We convert it directly to hash entries instead of going through convertNamed
232+ if ( named . type !== "object" ) {
233+ this . context . errors . add ( {
234+ severity : Severity . Critical ,
235+ message : "Internal error; expected union value to be an object"
236+ } ) ;
237+ return undefined ;
238+ }
239+ return this . convertObjectToHashEntries ( {
240+ object : named ,
241+ value : discriminatedUnionTypeInstance . value
242+ } ) ;
234243 }
235244 case "singleProperty" : {
236245 try {
@@ -271,19 +280,6 @@ export class DynamicTypeLiteralMapper {
271280 }
272281 }
273282
274- private extractHashEntries ( node : ruby . AstNode ) : ruby . HashEntry [ ] | undefined {
275- // This is a workaround to extract hash entries from a TypeLiteral
276- // We need to check if the node is a hash and extract its entries
277- // For now, we'll return an empty array if we can't extract entries
278- // The node should be a hash created by convertObject
279- if ( node instanceof ruby . TypeLiteral ) {
280- // TypeLiteral doesn't expose internal type, so we need to work around this
281- // by re-converting the value as an object
282- return undefined ;
283- }
284- return undefined ;
285- }
286-
287283 private convertEnum ( { enum_, value } : { enum_ : FernIr . dynamic . EnumType ; value : unknown } ) : ruby . AstNode {
288284 const name = this . getEnumValueName ( { enum_, value } ) ;
289285 if ( name == null ) {
@@ -426,29 +422,48 @@ export class DynamicTypeLiteralMapper {
426422 }
427423
428424 private convertObject ( { object, value } : { object : FernIr . dynamic . ObjectType ; value : unknown } ) : ruby . AstNode {
425+ const entries = this . convertObjectToHashEntries ( { object, value } ) ;
426+ if ( entries == null ) {
427+ return ruby . TypeLiteral . nop ( ) ;
428+ }
429+ return ruby . TypeLiteral . hash ( entries ) ;
430+ }
431+
432+ private convertObjectToHashEntries ( {
433+ object,
434+ value
435+ } : {
436+ object : FernIr . dynamic . ObjectType ;
437+ value : unknown ;
438+ } ) : ruby . HashEntry [ ] | undefined {
429439 if ( typeof value !== "object" || value == null ) {
430440 this . context . errors . add ( {
431441 severity : Severity . Critical ,
432442 message : `Expected object but got: ${ value == null ? "null" : typeof value } `
433443 } ) ;
434- return ruby . TypeLiteral . nop ( ) ;
444+ return undefined ;
435445 }
436446
437- return ruby . TypeLiteral . hash (
438- Object . entries ( value as Record < string , unknown > ) . map ( ( [ key , val ] ) => {
439- this . context . errors . scope ( key ) ;
447+ const entries : ruby . HashEntry [ ] = [ ] ;
448+
449+ for ( const [ key , val ] of Object . entries ( value as Record < string , unknown > ) ) {
450+ this . context . errors . scope ( key ) ;
451+ try {
440452 const property = object . properties . find ( ( p ) => p . name . wireValue === key ) ;
441- const typeReference = property ?. typeReference ?? { type : "unknown" } ;
453+ const typeReference = property ?. typeReference ?? { type : "unknown" as const } ;
442454 // Use snake_case property name for Ruby, falling back to wire value if not found
443455 const propertyName = property ?. name . name . snakeCase . safeName ?? key ;
444- const astNode = {
456+
457+ entries . push ( {
445458 key : ruby . TypeLiteral . string ( propertyName ) ,
446459 value : this . convert ( { typeReference, value : val } )
447- } ;
460+ } ) ;
461+ } finally {
448462 this . context . errors . unscope ( ) ;
449- return astNode ;
450- } )
451- ) ;
463+ }
464+ }
465+
466+ return entries ;
452467 }
453468
454469 private getValueAsNumber ( {
0 commit comments