@@ -18,6 +18,7 @@ import {
1818 getSessionEventsSchemaPath ,
1919 writeGeneratedFile ,
2020 collectDefinitions ,
21+ postProcessSchema ,
2122 resolveRef ,
2223 refTypeName ,
2324 isRpcMethod ,
@@ -512,18 +513,25 @@ function resolveSessionPropertyType(
512513) : string {
513514 // Handle $ref by resolving against schema definitions
514515 if ( propSchema . $ref ) {
515- const typeName = refTypeName ( propSchema . $ref ) ;
516- const className = typeToClassName ( typeName ) ;
517- if ( ! nestedClasses . has ( className ) ) {
518- const refSchema = resolveRef ( propSchema . $ref , sessionDefinitions ) ;
519- if ( refSchema ) {
520- if ( refSchema . enum && Array . isArray ( refSchema . enum ) ) {
521- return getOrCreateEnum ( className , "" , refSchema . enum as string [ ] , enumOutput ) ;
522- }
516+ const className = typeToClassName ( refTypeName ( propSchema . $ref ) ) ;
517+ const refSchema = resolveRef ( propSchema . $ref , sessionDefinitions ) ;
518+ if ( ! refSchema ) {
519+ return isRequired ? className : `${ className } ?` ;
520+ }
521+
522+ if ( refSchema . enum && Array . isArray ( refSchema . enum ) ) {
523+ const enumName = getOrCreateEnum ( className , "" , refSchema . enum as string [ ] , enumOutput , refSchema . description ) ;
524+ return isRequired ? enumName : `${ enumName } ?` ;
525+ }
526+
527+ if ( refSchema . type === "object" && refSchema . properties ) {
528+ if ( ! nestedClasses . has ( className ) ) {
523529 nestedClasses . set ( className , generateNestedClass ( className , refSchema , knownTypes , nestedClasses , enumOutput ) ) ;
524530 }
531+ return isRequired ? className : `${ className } ?` ;
525532 }
526- return isRequired ? className : `${ className } ?` ;
533+
534+ return resolveSessionPropertyType ( refSchema , parentClassName , propName , isRequired , knownTypes , nestedClasses , enumOutput ) ;
527535 }
528536 if ( propSchema . anyOf ) {
529537 const hasNull = propSchema . anyOf . some ( ( s ) => typeof s === "object" && ( s as JSONSchema7 ) . type === "null" ) ;
@@ -556,40 +564,15 @@ function resolveSessionPropertyType(
556564 }
557565 if ( propSchema . type === "array" && propSchema . items ) {
558566 const items = propSchema . items as JSONSchema7 ;
559- // Handle $ref in array items
560- if ( items . $ref ) {
561- const typeName = refTypeName ( items . $ref ) ;
562- const className = typeToClassName ( typeName ) ;
563- if ( ! nestedClasses . has ( className ) ) {
564- const refSchema = resolveRef ( items . $ref , sessionDefinitions ) ;
565- if ( refSchema ) {
566- nestedClasses . set ( className , generateNestedClass ( className , refSchema , knownTypes , nestedClasses , enumOutput ) ) ;
567- }
568- }
569- return isRequired ? `${ className } []` : `${ className } []?` ;
570- }
571- // Array of discriminated union (anyOf with shared discriminator)
572- if ( items . anyOf && Array . isArray ( items . anyOf ) ) {
573- const variants = items . anyOf . filter ( ( v ) : v is JSONSchema7 => typeof v === "object" ) ;
574- const discriminatorInfo = findDiscriminator ( variants ) ;
575- if ( discriminatorInfo ) {
576- const baseClassName = ( items . title as string ) ?? `${ parentClassName } ${ propName } Item` ;
577- const renamedBase = applyTypeRename ( baseClassName ) ;
578- const polymorphicCode = generatePolymorphicClasses ( baseClassName , discriminatorInfo . property , variants , knownTypes , nestedClasses , enumOutput , items . description ) ;
579- nestedClasses . set ( renamedBase , polymorphicCode ) ;
580- return isRequired ? `${ renamedBase } []` : `${ renamedBase } []?` ;
581- }
582- }
583- if ( items . type === "object" && items . properties ) {
584- const itemClassName = ( items . title as string ) ?? `${ parentClassName } ${ propName } Item` ;
585- nestedClasses . set ( itemClassName , generateNestedClass ( itemClassName , items , knownTypes , nestedClasses , enumOutput ) ) ;
586- return isRequired ? `${ itemClassName } []` : `${ itemClassName } []?` ;
587- }
588- if ( items . enum && Array . isArray ( items . enum ) ) {
589- const enumName = getOrCreateEnum ( parentClassName , `${ propName } Item` , items . enum as string [ ] , enumOutput , items . description , items . title as string | undefined ) ;
590- return isRequired ? `${ enumName } []` : `${ enumName } []?` ;
591- }
592- const itemType = schemaTypeToCSharp ( items , true , knownTypes ) ;
567+ const itemType = resolveSessionPropertyType (
568+ items ,
569+ parentClassName ,
570+ `${ propName } Item` ,
571+ true ,
572+ knownTypes ,
573+ nestedClasses ,
574+ enumOutput
575+ ) ;
593576 return isRequired ? `${ itemType } []` : `${ itemType } []?` ;
594577 }
595578 return schemaTypeToCSharp ( propSchema , isRequired , knownTypes ) ;
@@ -725,7 +708,8 @@ export async function generateSessionEvents(schemaPath?: string): Promise<void>
725708 console . log ( "C#: generating session-events..." ) ;
726709 const resolvedPath = schemaPath ?? ( await getSessionEventsSchemaPath ( ) ) ;
727710 const schema = cloneSchemaForCodegen ( JSON . parse ( await fs . readFile ( resolvedPath , "utf-8" ) ) as JSONSchema7 ) ;
728- const code = generateSessionEventsCode ( schema ) ;
711+ const processed = postProcessSchema ( schema ) ;
712+ const code = generateSessionEventsCode ( processed ) ;
729713 const outPath = await writeGeneratedFile ( "dotnet/src/Generated/SessionEvents.cs" , code ) ;
730714 console . log ( ` ✓ ${ outPath } ` ) ;
731715 await formatCSharpFile ( outPath ) ;
@@ -774,13 +758,24 @@ function stableStringify(value: unknown): string {
774758function resolveRpcType ( schema : JSONSchema7 , isRequired : boolean , parentClassName : string , propName : string , classes : string [ ] ) : string {
775759 // Handle $ref by resolving against schema definitions and generating the referenced class
776760 if ( schema . $ref ) {
777- const typeName = refTypeName ( schema . $ref ) ;
761+ const typeName = typeToClassName ( refTypeName ( schema . $ref ) ) ;
778762 const refSchema = resolveRef ( schema . $ref , rpcDefinitions ) ;
779- if ( refSchema && ! emittedRpcClasses . has ( typeName ) ) {
763+ if ( ! refSchema ) {
764+ return isRequired ? typeName : `${ typeName } ?` ;
765+ }
766+
767+ if ( refSchema . enum && Array . isArray ( refSchema . enum ) ) {
768+ const enumName = getOrCreateEnum ( typeName , "" , refSchema . enum as string [ ] , rpcEnumOutput , refSchema . description ) ;
769+ return isRequired ? enumName : `${ enumName } ?` ;
770+ }
771+
772+ if ( refSchema . type === "object" && refSchema . properties ) {
780773 const cls = emitRpcClass ( typeName , refSchema , "public" , classes ) ;
781774 if ( cls ) classes . push ( cls ) ;
775+ return isRequired ? typeName : `${ typeName } ?` ;
782776 }
783- return isRequired ? typeName : `${ typeName } ?` ;
777+
778+ return resolveRpcType ( refSchema , isRequired , parentClassName , propName , classes ) ;
784779 }
785780 // Handle anyOf: [T, null] → T? (nullable typed property)
786781 if ( schema . anyOf ) {
@@ -809,43 +804,17 @@ function resolveRpcType(schema: JSONSchema7, isRequired: boolean, parentClassNam
809804 }
810805 if ( schema . type === "array" && schema . items ) {
811806 const items = schema . items as JSONSchema7 ;
812- // Handle $ref in array items
813- if ( items . $ref ) {
814- const typeName = refTypeName ( items . $ref ) ;
815- const refSchema = resolveRef ( items . $ref , rpcDefinitions ) ;
816- if ( refSchema && ! emittedRpcClasses . has ( typeName ) ) {
817- const cls = emitRpcClass ( typeName , refSchema , "public" , classes ) ;
818- if ( cls ) classes . push ( cls ) ;
819- }
820- return isRequired ? `List<${ typeName } >` : `List<${ typeName } >?` ;
821- }
822807 if ( items . type === "object" && items . properties ) {
823808 const itemClass = ( items . title as string ) ?? singularPascal ( propName ) ;
824809 classes . push ( emitRpcClass ( itemClass , items , "public" , classes ) ) ;
825810 return isRequired ? `IList<${ itemClass } >` : `IList<${ itemClass } >?` ;
826811 }
827- if ( items . enum && Array . isArray ( items . enum ) ) {
828- const itemEnum = getOrCreateEnum (
829- parentClassName ,
830- `${ propName } Item` ,
831- items . enum as string [ ] ,
832- rpcEnumOutput ,
833- items . description ,
834- items . title as string | undefined ,
835- ) ;
836- return isRequired ? `IList<${ itemEnum } >` : `IList<${ itemEnum } >?` ;
837- }
838- const itemType = schemaTypeToCSharp ( items , true , rpcKnownTypes ) ;
812+ const itemType = resolveRpcType ( items , true , parentClassName , `${ propName } Item` , classes ) ;
839813 return isRequired ? `IList<${ itemType } >` : `IList<${ itemType } >?` ;
840814 }
841815 if ( schema . type === "object" && schema . additionalProperties && typeof schema . additionalProperties === "object" ) {
842816 const vs = schema . additionalProperties as JSONSchema7 ;
843- if ( vs . type === "object" && vs . properties ) {
844- const valClass = ( vs . title as string ) ?? `${ parentClassName } ${ propName } Value` ;
845- classes . push ( emitRpcClass ( valClass , vs , "public" , classes ) ) ;
846- return isRequired ? `IDictionary<string, ${ valClass } >` : `IDictionary<string, ${ valClass } >?` ;
847- }
848- const valueType = schemaTypeToCSharp ( vs , true , rpcKnownTypes ) ;
817+ const valueType = resolveRpcType ( vs , true , parentClassName , `${ propName } Value` , classes ) ;
849818 return isRequired ? `IDictionary<string, ${ valueType } >` : `IDictionary<string, ${ valueType } >?` ;
850819 }
851820 return schemaTypeToCSharp ( schema , isRequired , rpcKnownTypes ) ;
@@ -1045,15 +1014,9 @@ function emitServerInstanceMethod(
10451014 if ( typeof pSchema !== "object" ) continue ;
10461015 const isReq = requiredSet . has ( pName ) ;
10471016 const jsonSchema = pSchema as JSONSchema7 ;
1048- let csType : string ;
1049- // If the property has an enum, resolve to the generated enum type by title
1050- if ( jsonSchema . enum && Array . isArray ( jsonSchema . enum ) && requestClassName ) {
1051- const enumTitle = ( jsonSchema . title as string ) ?? `${ requestClassName } ${ toPascalCase ( pName ) } ` ;
1052- const match = generatedEnums . get ( enumTitle ) ;
1053- csType = match ? ( isReq ? match . enumName : `${ match . enumName } ?` ) : schemaTypeToCSharp ( jsonSchema , isReq , rpcKnownTypes ) ;
1054- } else {
1055- csType = schemaTypeToCSharp ( jsonSchema , isReq , rpcKnownTypes ) ;
1056- }
1017+ const csType = requestClassName
1018+ ? resolveRpcType ( jsonSchema , isReq , requestClassName , toPascalCase ( pName ) , classes )
1019+ : schemaTypeToCSharp ( jsonSchema , isReq , rpcKnownTypes ) ;
10571020 sigParams . push ( `${ csType } ${ pName } ${ isReq ? "" : " = null" } ` ) ;
10581021 bodyAssignments . push ( `${ toPascalCase ( pName ) } = ${ pName } ` ) ;
10591022 }
0 commit comments