import { connect } from 'react-redux' ; import { Dispatch } from 'redux' ; import { spawn } from 'child_process' ; import * as RequestBuilderActions from '../actions/requestBuilder' ; import * as ResponseViewerActions from '../actions/responseViewer' ; import * as ServiceListActions from '../actions/serviceList' ; import * as NodeProcessActions from '../actions/nodeProcess' ; import { AppState } from '../reducers/index' ; import { PolyglotService } from '../reducers/serviceList' ; import ServiceList , { ServiceListComponentMethods , ServiceListComponentState } from '../components/serviceList' ; import { checkConsoleErrorMessage , DEV_PATH_TO_POLYGLOT_BINARY , PROD_PATH_TO_POLYGLOT_BINARY } from './app' ; export interface ServiceListContainerProps { showNotification : ( title : string , explanation : string ) => void ; } param { string } serviceName param { string } serviceName returns { ( dispatch : Dispatch < AppState > , getState : ( ) => AppState ) => void } function handleMethodClick ( serviceName , methodName ) { return ( dispatch , getState ) => { try { const clickedService = getState ( ) . serviceListState . serviceMap . get ( serviceName ) ; if ( clickedService === undefined ) { throw new Error ( `Cannot find service ${ serviceName }` ) ; } const clickedMethod = clickedService . methodMap . get ( methodName ) ; if ( clickedMethod === undefined ) { throw new Error ( `Cannot find method ${ methodName } on service ${ serviceName }` ) ; } const prettyPrintedRequestTemplate = JSON . stringify ( clickedMethod . request , null , 2 ) ; const prettyPrintedResponseTemplate = JSON . stringify ( clickedMethod . response , null , 2 ) ; dispatch ( RequestBuilderActions . setClientStreamingRequest ( clickedMethod . clientStreaming ) ) ; dispatch ( RequestBuilderActions . setFullMethod ( `${ serviceName }/${ methodName }` ) ) ; dispatch ( RequestBuilderActions . setRequest ( prettyPrintedRequestTemplate ) ) ; dispatch ( ResponseViewerActions . setResponse ( prettyPrintedResponseTemplate ) ) ; dispatch ( ResponseViewerActions . setServerStreamingResponse ( clickedMethod . serverStreaming ) ) ; } catch ( e ) { console . error ( `Error when method was clicked ${ e }` ) ; } } ; } param { ( title : string , explanation : string ) => void } showNotification returns { ( dispatch : Dispatch < AppState > , getState : ( ) => AppState ) => void } function listServices ( showNotification ) { return ( dispatch , getState ) => { dispatch ( ResponseViewerActions . clearLogs ( ) ) ; dispatch ( RequestBuilderActions . setFullMethod ( '' ) ) ; dispatch ( RequestBuilderActions . setRequest ( '' ) ) ; dispatch ( ServiceListActions . importServices ( [ ] ) ) ; dispatch ( ResponseViewerActions . setResponse ( '' ) ) ; let pathToPolyglotBinary ; if ( process . env . NODE_ENV === 'development' ) { pathToPolyglotBinary = DEV_PATH_TO_POLYGLOT_BINARY ; } else { pathToPolyglotBinary = PROD_PATH_TO_POLYGLOT_BINARY ; } const polyglotCommand = 'java' ; const polyglotCommandLineArgs = [ '-jar' , pathToPolyglotBinary , '--command=list_services' , '--with_message=true' , '--list_output_format=json' ] ; if ( getState ( ) . settingsState . settingsDataState . protoDiscoveryRoot !== '' ) { polyglotCommandLineArgs . push ( `--proto_discovery_root=${ getState ( ) . settingsState . settingsDataState . protoDiscoveryRoot }` ) ; } if ( getState ( ) . serviceListState . serviceFilter !== '' ) { polyglotCommandLineArgs . push ( `--service_filter=${ getState ( ) . serviceListState . serviceFilter }` ) ; } if ( getState ( ) . serviceListState . methodFilter !== '' ) { polyglotCommandLineArgs . push ( `--method_filter=${ getState ( ) . serviceListState . methodFilter }` ) ; } if ( getState ( ) . settingsState . settingsDataState . deadlineMs > 0 ) { polyglotCommandLineArgs . push ( `--deadline_ms=${ getState ( ) . settingsState . settingsDataState . deadlineMs }` ) ; } if ( getState ( ) . settingsState . settingsDataState . addProtocIncludes !== '' ) { polyglotCommandLineArgs . push ( `--add_protoc_includes=${ getState ( ) . settingsState . settingsDataState . addProtocIncludes . split ( ',' ) . map ( ( elem ) => elem . trim ( ) ) . join ( ',' ) }` ) ; } const polyglot = spawn ( polyglotCommand , polyglotCommandLineArgs ) ; dispatch ( NodeProcessActions . addNodeProcessPid ( polyglot . pid ) ) ; let polyglotStdout = '' ; polyglot . stderr . on ( 'data' , ( data ) => { const log = new TextDecoder ( 'utf-8' ) . decode ( data as Buffer ) ; dispatch ( ResponseViewerActions . appendLog ( log ) ) ; } ) ; polyglot . stdout . on ( 'data' , ( data ) => { polyglotStdout += data ; } ) ; polyglot . on ( 'exit' , ( code ) => { dispatch ( NodeProcessActions . removeNodeProcessPid ( polyglot . pid ) ) ; if ( code === 0 ) { try { const parsedResponse = JSON . parse ( polyglotStdout as string ) as PolyglotService [ ] ; dispatch ( ServiceListActions . importServices ( parsedResponse ) ) ; } catch ( e ) { showNotification ( 'Error parsing list-services response:' , checkConsoleErrorMessage ) ; } } else { showNotification ( 'Error listing services: ' , checkConsoleErrorMessage ) ; } } ) ; } ; } param { AppState } state returns { RequestBuilderComponentState } param state function mapStateToProps ( state ) { return { serviceMap : state . serviceListState . serviceMap , serviceFilter : state . serviceListState . serviceFilter , methodFilter : state . serviceListState . methodFilter , } ; } param { Dispatch < AppState > } dispatch returns { RequestBuilderComponentMethods } function mapDispatchToProps ( dispatch , ownProps ) { return { handleMethodClick : ( serviceName , methodName ) => dispatch ( handleMethodClick ( serviceName , methodName ) ) , handleListServicesClick : ( ) => dispatch ( listServices ( ownProps . showNotification ) ) , handleMethodFilterChange : ( newMethodFilter ) => dispatch ( ServiceListActions . changeMethodFilter ( newMethodFilter ) ) , handleServiceFilterChange : ( newServiceFilter ) => dispatch ( ServiceListActions . changeServiceFilter ( newServiceFilter ) ) , } ; } export default ( connect ( mapStateToProps , mapDispatchToProps ) ( ServiceList ) ) ;