Code generator plugin option to exclude rpc methods by default
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.
Hey Taylor, there are some options:
- 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.
- Fork protobuf-ts and add the option.
- Generate all files, but only import and use the ones with
client_accessible = true. - 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.
Similar to https://github.com/timostamm/protobuf-ts/issues/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.