@@ -11,8 +11,11 @@ import {
1111 type DescMethodUnary ,
1212 type JsonValue as BufJsonValue ,
1313 type MessageInitShape ,
14+ type Registry ,
1415} from '@bufbuild/protobuf'
16+ import type { FileDescriptorSet } from '@bufbuild/protobuf/wkt'
1517import { Code , ConnectError , createClient , type CallOptions } from '@connectrpc/connect'
18+ import { buildDynamicRegistry } from './dynamicRegistry.js'
1619import type { JsonValue } from '@grpc-studio/shared'
1720import configManager from '../../config/configManager.js'
1821import type { FormattedGrpcError , StreamCallbacks , StreamHandle } from '../../types/index.js'
@@ -46,40 +49,51 @@ export type OutboundHeaders = Record<string, string>
4649export class ConnectInvoker {
4750 constructor ( private readonly transportProvider : ConnectTransportProvider = connectTransportProvider ) { }
4851
49- async invokeUnary ( method : DescMethodUnary , request : JsonValue | undefined , headers : OutboundHeaders ) : Promise < JsonValue > {
52+ async invokeUnary (
53+ method : DescMethodUnary ,
54+ request : JsonValue | undefined ,
55+ headers : OutboundHeaders ,
56+ fileDescriptorSet : FileDescriptorSet
57+ ) : Promise < JsonValue > {
58+ const registry = buildDynamicRegistry ( fileDescriptorSet )
5059 const response = await this . getClientMethod < UnaryClientMethod > ( method ) (
51- toProtoRequest ( method . input , request ) ,
60+ toProtoRequest ( method . input , request , registry ) ,
5261 this . buildCallOptions ( configManager . getClientConfig ( ) . rpc . unaryDeadlineMs , headers )
5362 )
5463
55- return toJsonResponse ( method . output , response )
64+ return toJsonResponse ( method . output , response , registry )
5665 }
5766
5867 async startServerStream (
5968 method : DescMethodServerStreaming ,
6069 request : JsonValue | undefined ,
6170 callbacks : StreamCallbacks ,
62- headers : OutboundHeaders
71+ headers : OutboundHeaders ,
72+ fileDescriptorSet : FileDescriptorSet
6373 ) : Promise < StreamHandle > {
74+ const registry = buildDynamicRegistry ( fileDescriptorSet )
6475 return this . startResponseStream (
6576 callbacks ,
6677 async ( signal ) => this . getClientMethod < ServerStreamingClientMethod > ( method ) (
67- toProtoRequest ( method . input , request ) ,
78+ toProtoRequest ( method . input , request , registry ) ,
6879 this . buildCallOptions ( configManager . getClientConfig ( ) . rpc . streamDeadlineMs , headers , signal )
6980 ) ,
70- method . output
81+ method . output ,
82+ registry
7183 )
7284 }
7385
7486 async startClientStream (
7587 method : DescMethodClientStreaming ,
7688 requests : RequestStream ,
7789 callbacks : StreamCallbacks ,
78- headers : OutboundHeaders
90+ headers : OutboundHeaders ,
91+ fileDescriptorSet : FileDescriptorSet
7992 ) : Promise < StreamHandle > {
8093 const abortController = new AbortController ( )
94+ const registry = buildDynamicRegistry ( fileDescriptorSet )
8195
82- this . pumpClientStream ( method , requests , callbacks , headers , abortController . signal )
96+ this . pumpClientStream ( method , requests , callbacks , headers , abortController . signal , registry )
8397 . catch ( ( error ) => {
8498 // Catch unhandled errors from pump to prevent unhandled promise rejections
8599 if ( ! abortController . signal . aborted ) {
@@ -98,26 +112,30 @@ export class ConnectInvoker {
98112 method : DescMethodBiDiStreaming ,
99113 requests : RequestStream ,
100114 callbacks : StreamCallbacks ,
101- headers : OutboundHeaders
115+ headers : OutboundHeaders ,
116+ fileDescriptorSet : FileDescriptorSet
102117 ) : Promise < StreamHandle > {
118+ const registry = buildDynamicRegistry ( fileDescriptorSet )
103119 return this . startResponseStream (
104120 callbacks ,
105121 async ( signal ) => this . getClientMethod < BidiStreamingClientMethod > ( method ) (
106- toConnectRequestStream ( method , requests ) ,
122+ toConnectRequestStream ( method , requests , registry ) ,
107123 this . buildCallOptions ( configManager . getClientConfig ( ) . rpc . streamDeadlineMs , headers , signal )
108124 ) ,
109- method . output
125+ method . output ,
126+ registry
110127 )
111128 }
112129
113130 private startResponseStream (
114131 callbacks : StreamCallbacks ,
115132 createStream : ( signal : AbortSignal ) => Promise < AsyncIterable < unknown > > ,
116- responseDesc : DescMessage
133+ responseDesc : DescMessage ,
134+ registry : Registry
117135 ) : StreamHandle {
118136 const abortController = new AbortController ( )
119137
120- this . pumpResponseStream ( createStream , responseDesc , callbacks , abortController . signal )
138+ this . pumpResponseStream ( createStream , responseDesc , callbacks , abortController . signal , registry )
121139 . catch ( ( error ) => {
122140 // Catch unhandled errors from pump to prevent unhandled promise rejections
123141 if ( ! abortController . signal . aborted ) {
@@ -136,13 +154,14 @@ export class ConnectInvoker {
136154 createStream : ( signal : AbortSignal ) => Promise < AsyncIterable < unknown > > ,
137155 responseDesc : DescMessage ,
138156 callbacks : StreamCallbacks ,
139- signal : AbortSignal
157+ signal : AbortSignal ,
158+ registry : Registry
140159 ) : Promise < void > {
141160 try {
142161 const stream = await createStream ( signal )
143162
144163 for await ( const message of stream ) {
145- callbacks . onData ( toJsonResponse ( responseDesc , message ) )
164+ callbacks . onData ( toJsonResponse ( responseDesc , message , registry ) )
146165 }
147166
148167 callbacks . onEnd ( )
@@ -158,15 +177,16 @@ export class ConnectInvoker {
158177 requests : RequestStream ,
159178 callbacks : StreamCallbacks ,
160179 headers : OutboundHeaders ,
161- signal : AbortSignal
180+ signal : AbortSignal ,
181+ registry : Registry
162182 ) : Promise < void > {
163183 try {
164184 const response = await this . getClientMethod < ClientStreamingClientMethod > ( method ) (
165- toConnectRequestStream ( method , requests ) ,
185+ toConnectRequestStream ( method , requests , registry ) ,
166186 this . buildCallOptions ( configManager . getClientConfig ( ) . rpc . streamDeadlineMs , headers , signal )
167187 )
168188
169- callbacks . onData ( toJsonResponse ( method . output , response ) )
189+ callbacks . onData ( toJsonResponse ( method . output , response , registry ) )
170190 callbacks . onEnd ( )
171191 } catch ( error ) {
172192 if ( ! signal . aborted ) {
@@ -206,19 +226,20 @@ export function formatConnectError(error: unknown): FormattedGrpcError {
206226 }
207227}
208228
209- function toProtoRequest ( desc : DescMessage , data : JsonValue | undefined ) : MessageInitShape < DescMessage > {
210- return fromJson ( desc , ( data ?? { } ) as BufJsonValue , { ignoreUnknownFields : true } ) as MessageInitShape < DescMessage >
229+ function toProtoRequest ( desc : DescMessage , data : JsonValue | undefined , registry : Registry ) : MessageInitShape < DescMessage > {
230+ return fromJson ( desc , ( data ?? { } ) as BufJsonValue , { ignoreUnknownFields : true , registry } ) as MessageInitShape < DescMessage >
211231}
212232
213- function toJsonResponse ( desc : DescMessage , message : unknown ) : JsonValue {
214- return toJson ( desc , message as never , { alwaysEmitImplicit : true , useProtoFieldName : true } ) as JsonValue
233+ function toJsonResponse ( desc : DescMessage , message : unknown , registry : Registry ) : JsonValue {
234+ return toJson ( desc , message as never , { alwaysEmitImplicit : true , useProtoFieldName : true , registry } ) as JsonValue
215235}
216236
217237async function * toConnectRequestStream (
218238 method : DescMethod ,
219- requests : RequestStream
239+ requests : RequestStream ,
240+ registry : Registry
220241) : AsyncIterable < MessageInitShape < DescMessage > > {
221242 for await ( const request of requests ) {
222- yield toProtoRequest ( method . input , request )
243+ yield toProtoRequest ( method . input , request , registry )
223244 }
224245}
0 commit comments