Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gRPC client streaming typescript not created. #1275

Closed
kkuehl opened this issue Sep 8, 2022 · 8 comments
Closed

gRPC client streaming typescript not created. #1275

kkuehl opened this issue Sep 8, 2022 · 8 comments

Comments

@kkuehl
Copy link

kkuehl commented Sep 8, 2022

Minimal protobuf example:

syntax = "proto3";

package filestream;

service FileService {
  rpc FileUploadCommand(stream FileUploadCommandRequest)
      returns (FileUploadCommandResponse) {}
  rpc FileDownloadCommand(FileDownloadCommandRequest)
      returns (stream FileDownloadCommandResponse) {}
}

enum FileCommand {
  FILE_UPLOAD = 0;
  FILE_DOWNLOAD = 1;
}

message FileContent {
  string filename = 1;
  bytes filecontent = 2;
}

message FileUploadCommandRequest { FileContent filecontent = 1; }

message FileUploadCommandResponse {
  string filename = 1;
  int64 filesize = 2;
}

message FileDownloadCommandRequest { string filename = 1; }

message FileDownloadCommandResponse { FileContent filecontent = 1; }

gRPC version: 1.48.1

protoc --version
libprotoc 3.19.4

protoc-gen-grpc-web version: 1.3.1-linux-x86_64

Command:

protoc -I=$DIR file.proto \
    --js_out=import_style=commonjs:$OUT_DIR \
    --grpc-web_out=import_style=typescript,mode=grpcwebtext:$OUT_DIR

Output:

/**
 * @fileoverview gRPC-Web generated client stub for filestream
 * @enhanceable
 * @public
 */

// GENERATED CODE -- DO NOT EDIT!


/* eslint-disable */
// @ts-nocheck


import * as grpcWeb from 'grpc-web';

import * as file_pb from './file_pb';


export class FileServiceClient {
  client_: grpcWeb.AbstractClientBase;
  hostname_: string;
  credentials_: null | { [index: string]: string; };
  options_: null | { [index: string]: any; };

  constructor (hostname: string,
               credentials?: null | { [index: string]: string; },
               options?: null | { [index: string]: any; }) {
    if (!options) options = {};
    if (!credentials) credentials = {};
    options['format'] = 'text';

    this.client_ = new grpcWeb.GrpcWebClientBase(options);
    this.hostname_ = hostname;
    this.credentials_ = credentials;
    this.options_ = options;
  }

  methodDescriptorFileDownloadCommand = new grpcWeb.MethodDescriptor(
    '/filestream.FileService/FileDownloadCommand',
    grpcWeb.MethodType.SERVER_STREAMING,
    file_pb.FileDownloadCommandRequest,
    file_pb.FileDownloadCommandResponse,
    (request: file_pb.FileDownloadCommandRequest) => {
      return request.serializeBinary();
    },
    file_pb.FileDownloadCommandResponse.deserializeBinary
  );

  fileDownloadCommand(
    request: file_pb.FileDownloadCommandRequest,
    metadata?: grpcWeb.Metadata): grpcWeb.ClientReadableStream<file_pb.FileDownloadCommandResponse> {
    return this.client_.serverStreaming(
      this.hostname_ +
        '/filestream.FileService/FileDownloadCommand',
      request,
      metadata || {},
      this.methodDescriptorFileDownloadCommand);
  }

}

Expectations: expected fileUploadCommand to be generated.

@kkuehl
Copy link
Author

kkuehl commented Sep 8, 2022

Similar results with

protoc -I=$DIR file.proto \
    --js_out=import_style=commonjs:$OUT_DIR \
    --grpc-web_out=import_style=commonjs+dts,mode=grpcwebtext:$OUT_DIR

Output:


import * as file_pb from './file_pb';


export class FileServiceClient {
  constructor (hostname: string,
               credentials?: null | { [index: string]: string; },
               options?: null | { [index: string]: any; });

  fileDownloadCommand(
    request: file_pb.FileDownloadCommandRequest,
    metadata?: grpcWeb.Metadata
  ): grpcWeb.ClientReadableStream<file_pb.FileDownloadCommandResponse>;

}

export class FileServicePromiseClient {
  constructor (hostname: string,
               credentials?: null | { [index: string]: string; },
               options?: null | { [index: string]: any; });

  fileDownloadCommand(
    request: file_pb.FileDownloadCommandRequest,
    metadata?: grpcWeb.Metadata
  ): grpcWeb.ClientReadableStream<file_pb.FileDownloadCommandResponse>;

}

@kkuehl
Copy link
Author

kkuehl commented Sep 8, 2022

Also attempted mode=grpcweb

protoc -I=$DIR file.proto \
    --js_out=import_style=commonjs:$OUT_DIR \
    --grpc-web_out=import_style=commonjs+dts,mode=grpcweb:$OUT_DIR

Output:

import * as grpcWeb from 'grpc-web';

import * as file_pb from './file_pb';


export class FileServiceClient {
  constructor (hostname: string,
               credentials?: null | { [index: string]: string; },
               options?: null | { [index: string]: any; });

  fileDownloadCommand(
    request: file_pb.FileDownloadCommandRequest,
    metadata?: grpcWeb.Metadata
  ): grpcWeb.ClientReadableStream<file_pb.FileDownloadCommandResponse>;

}

export class FileServicePromiseClient {
  constructor (hostname: string,
               credentials?: null | { [index: string]: string; },
               options?: null | { [index: string]: any; });

  fileDownloadCommand(
    request: file_pb.FileDownloadCommandRequest,
    metadata?: grpcWeb.Metadata
  ): grpcWeb.ClientReadableStream<file_pb.FileDownloadCommandResponse>;

}

And:

protoc -I=$DIR file.proto \
    --js_out=import_style=commonjs:$OUT_DIR \
    --grpc-web_out=import_style=typescript,mode=grpcweb:$OUT_DIR

Output:



import * as grpcWeb from 'grpc-web';

import * as file_pb from './file_pb';


export class FileServiceClient {
  client_: grpcWeb.AbstractClientBase;
  hostname_: string;
  credentials_: null | { [index: string]: string; };
  options_: null | { [index: string]: any; };

  constructor (hostname: string,
               credentials?: null | { [index: string]: string; },
               options?: null | { [index: string]: any; }) {
    if (!options) options = {};
    if (!credentials) credentials = {};
    options['format'] = 'binary';

    this.client_ = new grpcWeb.GrpcWebClientBase(options);
    this.hostname_ = hostname;
    this.credentials_ = credentials;
    this.options_ = options;
  }

  methodDescriptorFileDownloadCommand = new grpcWeb.MethodDescriptor(
    '/filestream.FileService/FileDownloadCommand',
    grpcWeb.MethodType.SERVER_STREAMING,
    file_pb.FileDownloadCommandRequest,
    file_pb.FileDownloadCommandResponse,
    (request: file_pb.FileDownloadCommandRequest) => {
      return request.serializeBinary();
    },
    file_pb.FileDownloadCommandResponse.deserializeBinary
  );

  fileDownloadCommand(
    request: file_pb.FileDownloadCommandRequest,
    metadata?: grpcWeb.Metadata): grpcWeb.ClientReadableStream<file_pb.FileDownloadCommandResponse> {
    return this.client_.serverStreaming(
      this.hostname_ +
        '/filestream.FileService/FileDownloadCommand',
      request,
      metadata || {},
      this.methodDescriptorFileDownloadCommand);
  }

}

@kkuehl
Copy link
Author

kkuehl commented Sep 8, 2022

This does not seem to be specifically a typescript problem:

protoc -I=$DIR file.proto \
    --js_out=import_style=commonjs:$OUT_DIR \
    --grpc-web_out=import_style=commonjs,mode=grpcwebtext:$OUT_DIR

Output:

/**
 * @fileoverview gRPC-Web generated client stub for filestream
 * @enhanceable
 * @public
 */

// GENERATED CODE -- DO NOT EDIT!


/* eslint-disable */
// @ts-nocheck



const grpc = {};
grpc.web = require('grpc-web');

const proto = {};
proto.filestream = require('./file_pb.js');

/**
 * @param {string} hostname
 * @param {?Object} credentials
 * @param {?grpc.web.ClientOptions} options
 * @constructor
 * @struct
 * @final
 */
proto.filestream.FileServiceClient =
    function(hostname, credentials, options) {
  if (!options) options = {};
  options.format = 'text';

  /**
   * @private @const {!grpc.web.GrpcWebClientBase} The client
   */
  this.client_ = new grpc.web.GrpcWebClientBase(options);

  /**
   * @private @const {string} The hostname
   */
  this.hostname_ = hostname;

};


/**
 * @param {string} hostname
 * @param {?Object} credentials
 * @param {?grpc.web.ClientOptions} options
 * @constructor
 * @struct
 * @final
 */
proto.filestream.FileServicePromiseClient =
    function(hostname, credentials, options) {
  if (!options) options = {};
  options.format = 'text';

  /**
   * @private @const {!grpc.web.GrpcWebClientBase} The client
   */
  this.client_ = new grpc.web.GrpcWebClientBase(options);

  /**
   * @private @const {string} The hostname
   */
  this.hostname_ = hostname;

};


/**
 * @const
 * @type {!grpc.web.MethodDescriptor<
 *   !proto.filestream.FileDownloadCommandRequest,
 *   !proto.filestream.FileDownloadCommandResponse>}
 */
const methodDescriptor_FileService_FileDownloadCommand = new grpc.web.MethodDescriptor(
  '/filestream.FileService/FileDownloadCommand',
  grpc.web.MethodType.SERVER_STREAMING,
  proto.filestream.FileDownloadCommandRequest,
  proto.filestream.FileDownloadCommandResponse,
  /**
   * @param {!proto.filestream.FileDownloadCommandRequest} request
   * @return {!Uint8Array}
   */
  function(request) {
    return request.serializeBinary();
  },
  proto.filestream.FileDownloadCommandResponse.deserializeBinary
);


/**
 * @param {!proto.filestream.FileDownloadCommandRequest} request The request proto
 * @param {?Object<string, string>=} metadata User defined
 *     call metadata
 * @return {!grpc.web.ClientReadableStream<!proto.filestream.FileDownloadCommandResponse>}
 *     The XHR Node Readable Stream
 */
proto.filestream.FileServiceClient.prototype.fileDownloadCommand =
    function(request, metadata) {
  return this.client_.serverStreaming(this.hostname_ +
      '/filestream.FileService/FileDownloadCommand',
      request,
      metadata || {},
      methodDescriptor_FileService_FileDownloadCommand);
};


/**
 * @param {!proto.filestream.FileDownloadCommandRequest} request The request proto
 * @param {?Object<string, string>=} metadata User defined
 *     call metadata
 * @return {!grpc.web.ClientReadableStream<!proto.filestream.FileDownloadCommandResponse>}
 *     The XHR Node Readable Stream
 */
proto.filestream.FileServicePromiseClient.prototype.fileDownloadCommand =
    function(request, metadata) {
  return this.client_.serverStreaming(this.hostname_ +
      '/filestream.FileService/FileDownloadCommand',
      request,
      metadata || {},
      methodDescriptor_FileService_FileDownloadCommand);
};


module.exports = proto.filestream;

@kkuehl
Copy link
Author

kkuehl commented Sep 8, 2022

Manually adding works.

methodDescriptorFileUploadloadCommand = new grpcWeb.MethodDescriptor(
    '/filestream.FileService/FileUploadCommand',
    grpcWeb.MethodType.SERVER_STREAMING,
    file_pb.FileUploadCommandRequest,
    file_pb.FileUploadCommandResponse,
    (request: file_pb.FileUploadCommandRequest) => {
      return request.serializeBinary();
    },
    file_pb.FileUploadCommandResponse.deserializeBinary
  );

  fileUploadCommand(
    request: file_pb.FileUploadCommandRequest,
    metadata?: grpcWeb.Metadata): grpcWeb.ClientReadableStream<file_pb.FileUploadCommandResponse> {
    return this.client_.serverStreaming(
      this.hostname_ +
        '/filestream.FileService/FileUploadCommand',
      request,
      metadata || {},
      this.methodDescriptorFileUploadCommand);
  }

@opporancisis
Copy link

Hi @kkuehl ,
I think that the client streaming is still not supported.
Look also: a ticket about the same topic and the roadmap.

@sampajano
Copy link
Collaborator

@opporancisis thanks for helping clarifying! That is right - Client streaming it not currently supported. Please follow the above mentioned thread if you're interested in this feature. Thanks!

@kkuehl
Copy link
Author

kkuehl commented Sep 13, 2022

Feel free to close ticket.

@sampajano
Copy link
Collaborator

thanks for reminder :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants