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

Code generator plugin option to exclude rpc methods by default #290

Closed
taylorcode opened this issue Apr 22, 2022 · 2 comments
Closed

Code generator plugin option to exclude rpc methods by default #290

taylorcode opened this issue Apr 22, 2022 · 2 comments

Comments

@taylorcode
Copy link

First of all thank you for developing this awesome library. I was able to integrate it into an existing stack which provides its own version of protoc and invokes the protoc-gen-ts binary directly. protoc-gen-ts is able to compile everything that I've thrown at it, and produces highly readable code.

At my company (Dropbox) it's a common practice to create services which contain rpc methods that are not intended for the browser. In order to use protobuf-ts's generated clients feature, I need some way to exclude such methods from the generated code.

I imagine that this could be represented as a custom option named client_accessible

service MyService {
  rpc GetFoo(FooRequest) returns (FooResponse) {};
  rpc GetBar(BarRequest) returns (BarResponse) {
    option client_accessible = true;
  };
}

In practice, most of the rpc methods are not intended for the browser/client. The reason for this is Dropbox has hundreds of existing services owned by different teams, and many of these services contain rpc methods for generating page HTML content.

Therefore, a more ideal solution for my use case would be a new plugin option such as exclude_rpc_methods_by_default and for individual rpc methods to opt in to being picked up by the code generator.

I can understand if this feature does not make sense to put into the core protobuf-ts plugin. Any guidance you can provide is greatly appreciated.

@timostamm
Copy link
Owner

Hey Taylor, there are some options:

  1. Re-organize your proto files, moving services intended for public consumption into a separate package, and only generate the public ones. This is a breaking change, of course.
  2. Fork protobuf-ts and add the option.
  3. Generate all files, but only import and use the ones with client_accessible = true.
  4. Filter the FileDescriptorSet before generating code.

Some background on option 4: If you run protoc to generate code, it parses the proto files and creates a FileDescriptorSet. This data structure describes the proto files. It is a bit similar to an AST, but higher level. You can let protoc create a file descriptor set from your source files, manipulate it, then generate code based on the manipulated descriptor set.

buf (protoc replacement) makes this a bit easier because it supports the JSON format for file descriptor sets. For example, let's say you have this service:

service MyService {
  rpc GetBar(Example) returns (Example) {
    option (docs.client_accessible) = true;
  }
}

You would use the following command to compile all proto files into a file descriptor set in JSON format:

buf build --output image.json

This image contains your custom option as well:

      "service": [
        {
          "name": "MyService",
          "method": [
            {
              "name": "GetBar",
              "inputType": ".docs.Example",
              "outputType": ".docs.Example",
              "options": {
                "[docs.client_accessible]": true
              }
            }
          ]
        }
      ],

You can remove the method from the image, then run buf generate image.json to generate code from it.

There are caveats, though: The file descriptor set also contains comments, and if you remove just a few methods from a service, it is possible that comments for other methods on that service show the wrong comments. This would not matter if your custom option would apply to services.

@timostamm
Copy link
Owner

Similar to #183, I think the best option here is to write a plugin. The plan is to switch the base types to the ones provided by protobuf-es. This will give us a much improved plugin framework that should make it rather trivial to write a custom plugin that excludes some RPCs based on an option.

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

2 participants