Generate FieldMask utilities for protobuf,
support Go, maybe more programing languages later. FieldMask is a protobuf message type,
it's used to represent a set of fields those should be contained in response, and sent to Client
.
It looks like grapgql
but only takes effect on the server inside calls.
To help developer to avoid repeating codes to deal with FieldMask
message, this plugin generates a set of utilities to
deal with FieldMask
message.
1. Masking gRPC response case
2. Incremental update case
in
messageMask_$field
to in
message type which declare in in.FieldMask
option.FieldMask_Filter
and FieldMask_Prune
to in
message, quickly apply field mask. Masked_$field
to $out_FieldMask
support quickly judge field masking. in
fields in incremental updating
case.go install github.com/yeqown/protoc-gen-fieldmask@latest
protoc \
-I. \
-I$YOUR_PROTO_PATH \
--go_out=paths=source_relative:. \
--fieldmask_out=paths=source_relative,lang=go:. \
example.proto
syntax = "proto3";
import "google/protobuf/field_mask.proto";
message UserInfoRequest {
string user_id = 1;
google.protobuf.FieldMask field_mask = 2 [
// generate MaskIn_XXX and MaskedIn_XXX, xxx are fields in in message (UserInfoRequest).
(fieldmask.option.Option).in = {gen: true},
// generate MaskOut_XXX and MaskedOut_XXX, xxx are fields in out message (UserInfoResponse).
// Notice that:
// 1. you must set message to out message name, and in and out message should in a same proto file.
// 2. if out message is not specified, it will not generated correctly.
(fieldmask.option.Option).out = {gen: true, message:"UserInfoResponse"}
];
}
message Address {
string country = 1;
string province = 2;
}
message UserInfoResponse {
string user_id = 1;
string name = 2;
string email = 3;
Address address = 4;
}
cd examples && make gen-pb
# or generate them manually
cd examples
protoc \
-I./pb \
-I../proto \
--go_out=paths=source_relative:./pb \
--fieldmask_out=paths=source_relative,lang=go:./pb \
./pb/user.proto
func main() {
req := &normal.UserInfoRequest{
UserId: "123123",
FieldMask: nil,
}
// enable field mask on specific fields.
req.MaskOut_Email()
req.MaskOut_Name()
filter := req.FieldMask_Filter()
// or use prune mode, so clear fields those are masked.
// prune := req.FieldMask_Prune()
resp := &normal.UserInfoResponse{
UserId: "69781",
Name: "yeqown",
Email: "yeqown@gmail.com",
Address: &normal.Address{
Country: "China",
Province: "Sichuan",
},
}
// makes filter or prune effect on resp.
prune.Mask(resp)
}
on the other hand, you can take FieldMask effect before the resp
has been filled,
so that you can ignore unnecessary calculating or remote calls:
func main() {
req := &normal.UserInfoRequest{
UserId: "123123",
FieldMask: nil,
}
// enable field mask on specific fields.
req.MaskOut_Email()
req.MaskOut_Name()
filter := req.FieldMask_Filter()
resp := new(normal.UserInfoResponse)
if filter.Masked_Email() {
resp.Email = "yeqown@gmail.com"
}
if filter.Masked_Name() {
resp.Name = "yeqown"
}
}
debugdata
protoc-gen-debug
: go install github.com/lyft/protoc-gen-star/protoc-gen-debug@latest
compile target proto file with protoc-gen-debug
:
protoc \
-I=./examples/pb \
-I=./proto \
--plugin=protoc-gen-debug=${debug_path} \
--debug_out="./internal/module/debugdata:." \
./examples/pb/user.proto