@@ -17,6 +17,7 @@ import {
1717 getRpcSchemaTypeName ,
1818 getSessionEventsSchemaPath ,
1919 isNodeFullyExperimental ,
20+ isObjectSchema ,
2021 isRpcMethod ,
2122 REPO_ROOT ,
2223 writeGeneratedFile ,
@@ -596,6 +597,7 @@ export async function generateSessionEvents(schemaPath?: string): Promise<void>
596597// ══════════════════════════════════════════════════════════════════════════════
597598
598599let emittedRpcClasses = new Set < string > ( ) ;
600+ let emittedRpcEnumResultTypes = new Set < string > ( ) ;
599601let experimentalRpcTypes = new Set < string > ( ) ;
600602let rpcKnownTypes = new Map < string , string > ( ) ;
601603let rpcEnumOutput : string [ ] = [ ] ;
@@ -718,6 +720,21 @@ function emitRpcClass(className: string, schema: JSONSchema7, visibility: "publi
718720 return lines . join ( "\n" ) ;
719721}
720722
723+ /**
724+ * Emit the type for a non-object RPC result schema (e.g., a bare enum).
725+ * Returns the C# type name to use in method signatures. For enums, ensures the enum
726+ * is created via getOrCreateEnum. For other primitives, returns the mapped C# type.
727+ */
728+ function emitNonObjectResultType ( typeName : string , schema : JSONSchema7 , classes : string [ ] ) : string {
729+ if ( schema . enum && Array . isArray ( schema . enum ) ) {
730+ const enumName = getOrCreateEnum ( "" , typeName , schema . enum as string [ ] , rpcEnumOutput , schema . description , typeName ) ;
731+ emittedRpcEnumResultTypes . add ( enumName ) ;
732+ return enumName ;
733+ }
734+ // For other non-object types, use the basic type mapping
735+ return schemaTypeToCSharp ( schema , true , rpcKnownTypes ) ;
736+ }
737+
721738/**
722739 * Emit ServerRpc as an instance class (like SessionRpc but without sessionId).
723740 */
@@ -803,12 +820,16 @@ function emitServerInstanceMethod(
803820 groupExperimental : boolean
804821) : void {
805822 const methodName = toPascalCase ( name ) ;
806- const resultClassName = resultTypeName ( method ) ;
823+ let resultClassName = resultTypeName ( method ) ;
807824 if ( method . stability === "experimental" ) {
808825 experimentalRpcTypes . add ( resultClassName ) ;
809826 }
810- const resultClass = emitRpcClass ( resultClassName , method . result , "public" , classes ) ;
811- if ( resultClass ) classes . push ( resultClass ) ;
827+ if ( isObjectSchema ( method . result ) ) {
828+ const resultClass = emitRpcClass ( resultClassName , method . result , "public" , classes ) ;
829+ if ( resultClass ) classes . push ( resultClass ) ;
830+ } else if ( method . result ) {
831+ resultClassName = emitNonObjectResultType ( resultClassName , method . result , classes ) ;
832+ }
812833
813834 const paramEntries = method . params ?. properties ? Object . entries ( method . params . properties ) : [ ] ;
814835 const requiredSet = new Set ( method . params ?. required || [ ] ) ;
@@ -890,12 +911,16 @@ function emitSessionRpcClasses(node: Record<string, unknown>, classes: string[])
890911
891912function emitSessionMethod ( key : string , method : RpcMethod , lines : string [ ] , classes : string [ ] , indent : string , groupExperimental : boolean ) : void {
892913 const methodName = toPascalCase ( key ) ;
893- const resultClassName = resultTypeName ( method ) ;
914+ let resultClassName = resultTypeName ( method ) ;
894915 if ( method . stability === "experimental" ) {
895916 experimentalRpcTypes . add ( resultClassName ) ;
896917 }
897- const resultClass = emitRpcClass ( resultClassName , method . result , "public" , classes ) ;
898- if ( resultClass ) classes . push ( resultClass ) ;
918+ if ( isObjectSchema ( method . result ) ) {
919+ const resultClass = emitRpcClass ( resultClassName , method . result , "public" , classes ) ;
920+ if ( resultClass ) classes . push ( resultClass ) ;
921+ } else if ( method . result ) {
922+ resultClassName = emitNonObjectResultType ( resultClassName , method . result , classes ) ;
923+ }
899924
900925 const paramEntries = ( method . params ?. properties ? Object . entries ( method . params . properties ) : [ ] ) . filter ( ( [ k ] ) => k !== "sessionId" ) ;
901926 const requiredSet = new Set ( method . params ?. required || [ ] ) ;
@@ -982,8 +1007,12 @@ function emitClientSessionApiRegistration(clientSchema: Record<string, unknown>,
9821007 for ( const { methods } of groups ) {
9831008 for ( const method of methods ) {
9841009 if ( method . result ) {
985- const resultClass = emitRpcClass ( resultTypeName ( method ) , method . result , "public" , classes ) ;
986- if ( resultClass ) classes . push ( resultClass ) ;
1010+ if ( isObjectSchema ( method . result ) ) {
1011+ const resultClass = emitRpcClass ( resultTypeName ( method ) , method . result , "public" , classes ) ;
1012+ if ( resultClass ) classes . push ( resultClass ) ;
1013+ } else {
1014+ emitNonObjectResultType ( resultTypeName ( method ) , method . result , classes ) ;
1015+ }
9871016 }
9881017
9891018 if ( method . params ?. properties && Object . keys ( method . params . properties ) . length > 0 ) {
@@ -1079,6 +1108,7 @@ function emitClientSessionApiRegistration(clientSchema: Record<string, unknown>,
10791108
10801109function generateRpcCode ( schema : ApiSchema ) : string {
10811110 emittedRpcClasses . clear ( ) ;
1111+ emittedRpcEnumResultTypes . clear ( ) ;
10821112 experimentalRpcTypes . clear ( ) ;
10831113 rpcKnownTypes . clear ( ) ;
10841114 rpcEnumOutput = [ ] ;
@@ -1122,7 +1152,7 @@ internal static class Diagnostics
11221152 if ( clientSessionParts . length > 0 ) lines . push ( ...clientSessionParts , "" ) ;
11231153
11241154 // Add JsonSerializerContext for AOT/trimming support
1125- const typeNames = [ ...emittedRpcClasses ] . sort ( ) ;
1155+ const typeNames = [ ...emittedRpcClasses , ... emittedRpcEnumResultTypes ] . sort ( ) ;
11261156 if ( typeNames . length > 0 ) {
11271157 lines . push ( `[JsonSourceGenerationOptions(` ) ;
11281158 lines . push ( ` JsonSerializerDefaults.Web,` ) ;
0 commit comments