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

Not clear how to use the generated client implementations #495

Closed
torkelrogstad opened this issue Jan 28, 2022 · 6 comments · Fixed by #511
Closed

Not clear how to use the generated client implementations #495

torkelrogstad opened this issue Jan 28, 2022 · 6 comments · Fixed by #511
Labels

Comments

@torkelrogstad
Copy link
Contributor

Thanks for creating what looks like a great, idomatic TS code generator.

However, I'm having some issues getting started. I've generated a TS file from my Proto file, with (among other things), this:

export interface HelloWorldService {
  Ping(request: PingRequest): Promise<PingResponse>;
}

export class HelloWorldServiceClientImpl implements HelloWorldService {
  private readonly rpc: Rpc;
  constructor(rpc: Rpc) {
    this.rpc = rpc;
    this.Ping = this.Ping.bind(this);
  }
  Ping(request: PingRequest): Promise<PingResponse> {
    const data = PingRequest.encode(request).finish();
    const promise = this.rpc.request(
      "helloworld.v1.HelloWorldService",
      "Ping",
      data
    );
    return promise.then((data) => PingResponse.decode(new _m0.Reader(data)));
  }
}

What am I supposed to stick into new HelloWorldServiceClientImpl? The goal here is to create a Node.js client.

@torkelrogstad
Copy link
Contributor Author

Got this working:

const conn = new grpc.Client(
  "localhost:8765",
  grpc.credentials.createInsecure()
);

type RpcImpl = (
  service: string,
  method: string,
  data: Uint8Array
) => Promise<Uint8Array>;

const sendRequest: RpcImpl = (service, method, data) => {
  // Conventionally in gRPC, the request path looks like
  //   "package.names.ServiceName/MethodName",
  // we therefore construct such a string
  const path = `${service}/${method}`;

  return new Promise((resolve, reject) => {
    // makeUnaryRequest transmits the result (and error) with a callback
    // transform this into a promise!
    const resultCallback: UnaryCallback<any> = (err, res) => {
      if (err) {
        return reject(err);
      }
      resolve(res);
    };

    function passThrough(argument: any) {
      return argument;
    }

    // Using passThrough as the serialize and deserialize functions
    conn.makeUnaryRequest(path, passThrough, passThrough, data, resultCallback);
  });
};

This was not obvious at all. Am I missing something from the documentation, or is there some generated code somewhere I haven't seen?

@torkelrogstad
Copy link
Contributor Author

I see that if I set outputServices=generic-definitions as an option, I get generated stubs that seems to do everything I need for me. However, I then have to resort to handling responses with callbacks. Is there any reason that the default behavior is to not generate a complete client?

@stephenh
Copy link
Owner

stephenh commented Feb 15, 2022

Hey @torkelrogstad , sorry for the really late follow up here, but right, as you've noticed, ts-proto is not a super-polished / user-friendly / out-of-the-box RPC framework.

Instead, it's more like a swiss-army knife of twirp (originally) / grpc-web / nest / grpc.io / etc. options that has learned to do many different things, but not necessarily any one thing amazingly well. It's strength is in its either configurablility or hackability to fit into custom/bespoke RPC stacks (b/c at least historically the grpc RPC environment was pretty fragmented; it seems like it's becoming less so especially with grpc.io).

This not really on purpose, but just how it's gone.

It'd be great to have a better out-of-box experience; if you want to copy/paste what you have ^ into either a "Getting Started" or "Basic RPC Implementation" section of the readme, or a new dedicated page, that would be really great.

Thank you!

@stephenh
Copy link
Owner

🎉 This issue has been resolved in version 1.105.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

@avegancafe
Copy link

avegancafe commented Jun 16, 2022

What is makeUnaryRequest or conn? trying to use this lib and struggling to find a usable grpc web client and I see this example in the docs, but I think might not be fully. Any help or prior context would be greatly appreciated! 🙏 Happy to open a PR with a fully working simple client when I figure one out as well of course

@lf-jason-jia
Copy link

Just to mention, the request path should be (at least with grpc-js): /${service}/${method}, so "/" must be in front. Otherwise you would get: Error: 13 INTERNAL: Received RST_STREAM with code 1

jayakrishnancn added a commit to jayakrishnancn/ts-proto that referenced this issue Aug 18, 2024
Not clear how to use the generated client implementations

thanks to @torkelrogstad 
ref: stephenh#495
stephenh pushed a commit that referenced this issue Aug 18, 2024
Not clear how to use the generated client implementations

thanks to @torkelrogstad 
ref: #495
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants