@@ -595,7 +595,6 @@ export async function generateSessionEvents(schemaPath?: string): Promise<void>
595595// RPC TYPES
596596// ══════════════════════════════════════════════════════════════════════════════
597597
598- let emittedRpcClasses = new Set < string > ( ) ;
599598let emittedRpcClassSchemas = new Map < string , string > ( ) ;
600599let experimentalRpcTypes = new Set < string > ( ) ;
601600let rpcKnownTypes = new Map < string , string > ( ) ;
@@ -628,20 +627,6 @@ function stableStringify(value: unknown): string {
628627 return JSON . stringify ( value ) ;
629628}
630629
631- function chooseRpcClassName ( preferredName : string , fallbackName : string , schema : JSONSchema7 ) : string {
632- const schemaKey = stableStringify ( schema ) ;
633- const existingPreferred = emittedRpcClassSchemas . get ( preferredName ) ;
634- if ( ! existingPreferred || existingPreferred === schemaKey ) return preferredName ;
635-
636- let candidate = fallbackName ;
637- let suffix = 2 ;
638- while ( true ) {
639- const existing = emittedRpcClassSchemas . get ( candidate ) ;
640- if ( ! existing || existing === schemaKey ) return candidate ;
641- candidate = `${ fallbackName } ${ suffix ++ } ` ;
642- }
643- }
644-
645630function resolveRpcType ( schema : JSONSchema7 , isRequired : boolean , parentClassName : string , propName : string , classes : string [ ] ) : string {
646631 // Handle anyOf: [T, null] → T? (nullable typed property)
647632 if ( schema . anyOf ) {
@@ -664,10 +649,8 @@ function resolveRpcType(schema: JSONSchema7, isRequired: boolean, parentClassNam
664649 if ( schema . type === "array" && schema . items ) {
665650 const items = schema . items as JSONSchema7 ;
666651 if ( items . type === "object" && items . properties ) {
667- const defaultName = ( items . title as string ) ?? singularPascal ( propName ) ;
668- const contextualName = `${ parentClassName } ${ defaultName } ` ;
669- const itemClass = chooseRpcClassName ( defaultName , contextualName , items ) ;
670- if ( ! emittedRpcClasses . has ( itemClass ) ) classes . push ( emitRpcClass ( itemClass , items , "public" , classes ) ) ;
652+ const itemClass = ( items . title as string ) ?? singularPascal ( propName ) ;
653+ classes . push ( emitRpcClass ( itemClass , items , "public" , classes ) ) ;
671654 return isRequired ? `List<${ itemClass } >` : `List<${ itemClass } >?` ;
672655 }
673656 const itemType = schemaTypeToCSharp ( items , true , rpcKnownTypes ) ;
@@ -687,9 +670,18 @@ function resolveRpcType(schema: JSONSchema7, isRequired: boolean, parentClassNam
687670}
688671
689672function emitRpcClass ( className : string , schema : JSONSchema7 , visibility : "public" | "internal" , extraClasses : string [ ] ) : string {
690- if ( emittedRpcClasses . has ( className ) ) return "" ;
691- emittedRpcClasses . add ( className ) ;
692- emittedRpcClassSchemas . set ( className , stableStringify ( schema ) ) ;
673+ const schemaKey = stableStringify ( schema ) ;
674+ const existingSchema = emittedRpcClassSchemas . get ( className ) ;
675+ if ( existingSchema ) {
676+ if ( existingSchema !== schemaKey ) {
677+ throw new Error (
678+ `Conflicting RPC class name "${ className } " for different schemas. Add a schema title/withTypeName to disambiguate.`
679+ ) ;
680+ }
681+ return "" ;
682+ }
683+
684+ emittedRpcClassSchemas . set ( className , schemaKey ) ;
693685
694686 const requiredSet = new Set ( schema . required || [ ] ) ;
695687 const lines : string [ ] = [ ] ;
@@ -718,7 +710,7 @@ function emitRpcClass(className: string, schema: JSONSchema7, visibility: "publi
718710 else if ( csharpType === "object" ) defaultVal = " = null!;" ;
719711 else if ( csharpType . startsWith ( "List<" ) || csharpType . startsWith ( "Dictionary<" ) ) {
720712 propAccessors = "{ get => field ??= []; set; }" ;
721- } else if ( emittedRpcClasses . has ( csharpType ) ) {
713+ } else if ( emittedRpcClassSchemas . has ( csharpType ) ) {
722714 propAccessors = "{ get => field ??= new(); set; }" ;
723715 }
724716 }
@@ -1089,7 +1081,6 @@ function emitClientSessionApiRegistration(clientSchema: Record<string, unknown>,
10891081}
10901082
10911083function generateRpcCode ( schema : ApiSchema ) : string {
1092- emittedRpcClasses . clear ( ) ;
10931084 emittedRpcClassSchemas . clear ( ) ;
10941085 experimentalRpcTypes . clear ( ) ;
10951086 rpcKnownTypes . clear ( ) ;
@@ -1134,7 +1125,7 @@ internal static class Diagnostics
11341125 if ( clientSessionParts . length > 0 ) lines . push ( ...clientSessionParts , "" ) ;
11351126
11361127 // Add JsonSerializerContext for AOT/trimming support
1137- const typeNames = [ ...emittedRpcClasses ] . sort ( ) ;
1128+ const typeNames = [ ...emittedRpcClassSchemas . keys ( ) ] . sort ( ) ;
11381129 if ( typeNames . length > 0 ) {
11391130 lines . push ( `[JsonSourceGenerationOptions(` ) ;
11401131 lines . push ( ` JsonSerializerDefaults.Web,` ) ;
0 commit comments