import { credentials , ServiceDefinition , Metadata , ServiceError , requestCallback , ClientWritableStream , ClientReadableStream , ClientDuplexStream } from "grpc" ; import EnvoyContext from "./envoy-context" ; import EnvoyGrpcRequestParams , { EnvoyGrpcRequestInit } from "./envoy-grpc-request-params" ; import { RequestFunc , EnvoyClient , ClientConstructor , EnvoyClientConstructor , EnvoyClientFuncEnabled , HttpHeader , ChannelFactoryOverride } from "./types" ; param name internal function makeAsyncFunc ( name ) { return async function ( this , request , options ? ) { const params = new EnvoyGrpcRequestParams ( this . envoyContext , options ) ; return new Promise ( ( resolve , reject ) => { Object . getPrototypeOf ( Object . getPrototypeOf ( this ) ) [ name ] . call ( this , request , params . assembleRequestMeta ( ) , { host : this . originalAddress } , ( error , response ) => { if ( error ) { reject ( error ) ; return ; } resolve ( response ) ; } ) ; } ) ; } ; } param name function wrapClientStreamFunc ( name ) { return function ( this , callback , options ? ) : ClientWritableStream < any > { const params = new EnvoyGrpcRequestParams ( this . envoyContext , options ) ; return Object . getPrototypeOf ( Object . getPrototypeOf ( this ) ) [ name ] . call ( this , params . assembleRequestMeta ( ) , { host : this . originalAddress } , callback ) ; } ; } param name function wrapServerStream ( name ) { return function ( this , request , options ? ) : ClientReadableStream < any > { const params = new EnvoyGrpcRequestParams ( this . envoyContext , options ) ; return Object . getPrototypeOf ( Object . getPrototypeOf ( this ) ) [ name ] . call ( this , request , params . assembleRequestMeta ( ) , { host : this . originalAddress } ) ; } ; } param name function wrapBidiStream ( name ) { return function ( this , options ? ) : ClientDuplexStream < any , any > { const params = new EnvoyGrpcRequestParams ( this . envoyContext , options ) ; return Object . getPrototypeOf ( Object . getPrototypeOf ( this ) ) [ name ] . call ( this , params . assembleRequestMeta ( ) , { host : this . originalAddress } ) ; } ; } param constructor export default function envoyProtoDecorator < T extends EnvoyClient > ( constructor , channelFactoryOverride = undefined ) { const constructorAlias = constructor ; const { service } = constructorAlias ; const clazz = class extends constructor implements EnvoyClient { readonly originalAddress : string ; readonly envoyContext : EnvoyContext ; constructor ( address , ctx ) { let envoyContext ; if ( ctx instanceof EnvoyContext ) { envoyContext = ctx ; } else { envoyContext = new EnvoyContext ( ctx ) ; } const actualAddr = envoyContext . shouldCallWithoutEnvoy ( address ) ? address : `${ envoyContext . envoyEgressAddr }:${ envoyContext . envoyEgressPort }` ; super ( actualAddr , credentials . createInsecure ( ) , { channelFactoryOverride } ) ; this . originalAddress = address ; this . envoyContext = envoyContext ; } } as EnvoyClientConstructor < T > ; const prototype = clazz . prototype as EnvoyClientFuncEnabled ; for ( const name of Object . keys ( service ) ) { const method = service [ name ] ; const { requestStream , responseStream } = method ; if ( ! requestStream && ! responseStream ) { prototype [ name ] = makeAsyncFunc ( name ) ; } else if ( method . requestStream && ! method . responseStream ) { prototype [ name ] = wrapClientStreamFunc ( name ) ; } else if ( ! method . requestStream && method . responseStream ) { prototype [ name ] = wrapServerStream ( name ) ; } else { prototype [ name ] = wrapBidiStream ( name ) ; } const { originalName } = method ; if ( originalName ) { prototype [ originalName ] = prototype [ name ] ; } } return clazz ; }