From e25a0bf7cfbb8b6a567c134be46ccaa85666c1bd Mon Sep 17 00:00:00 2001 From: Alex Stephen <1325798+rambleraptor@users.noreply.github.com> Date: Fri, 11 Oct 2024 01:03:07 -0400 Subject: [PATCH] objects can have properties (#30) Closes #26 This allows us to write objects inline with properties. --- example/bookstore/v1/bookstore.pb.go | 350 ++++++++++++-------- example/bookstore/v1/bookstore.proto | 11 + example/bookstore/v1/bookstore.swagger.json | 21 ++ example/bookstore/v1/bookstore.yaml | 10 + example/bookstore/v1/bookstore_openapi.json | 6 + parser/parser.go | 32 +- schema/resourcedefinition.pb.go | 104 +++--- schema/resourcedefinition.proto | 6 +- validator/validator.go | 18 + writer/openapi/openapi.go | 49 ++- writer/openapi/utils.go | 116 ++++--- writer/proto/proto.go | 10 +- writer/proto/resource.go | 148 +++++---- 13 files changed, 547 insertions(+), 334 deletions(-) diff --git a/example/bookstore/v1/bookstore.pb.go b/example/bookstore/v1/bookstore.pb.go index 9926b77..8f246be 100644 --- a/example/bookstore/v1/bookstore.pb.go +++ b/example/bookstore/v1/bookstore.pb.go @@ -29,6 +29,8 @@ type Book struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // Field for author. + Author []*Book_Author `protobuf:"bytes,5,rep,name=author,proto3" json:"author,omitempty"` // Field for isbn. Isbn []string `protobuf:"bytes,1,rep,name=isbn,proto3" json:"isbn,omitempty"` // Field for price. @@ -75,6 +77,13 @@ func (*Book) Descriptor() ([]byte, []int) { return file_example_bookstore_v1_bookstore_proto_rawDescGZIP(), []int{0} } +func (x *Book) GetAuthor() []*Book_Author { + if x != nil { + return x.Author + } + return nil +} + func (x *Book) GetIsbn() []string { if x != nil { return x.Isbn @@ -532,6 +541,63 @@ func (x *ApplyBookRequest) GetBook() *Book { return nil } +type Book_Author struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Field for firstName. + FirstName string `protobuf:"bytes,1,opt,name=firstName,proto3" json:"firstName,omitempty"` + // Field for lastName. + LastName string `protobuf:"bytes,2,opt,name=lastName,proto3" json:"lastName,omitempty"` +} + +func (x *Book_Author) Reset() { + *x = Book_Author{} + if protoimpl.UnsafeEnabled { + mi := &file_example_bookstore_v1_bookstore_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Book_Author) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Book_Author) ProtoMessage() {} + +func (x *Book_Author) ProtoReflect() protoreflect.Message { + mi := &file_example_bookstore_v1_bookstore_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Book_Author.ProtoReflect.Descriptor instead. +func (*Book_Author) Descriptor() ([]byte, []int) { + return file_example_bookstore_v1_bookstore_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *Book_Author) GetFirstName() string { + if x != nil { + return x.FirstName + } + return "" +} + +func (x *Book_Author) GetLastName() string { + if x != nil { + return x.LastName + } + return "" +} + var File_example_bookstore_v1_bookstore_proto protoreflect.FileDescriptor var file_example_bookstore_v1_bookstore_proto_rawDesc = []byte{ @@ -549,117 +615,125 @@ var file_example_bookstore_v1_bookstore_proto_rawDesc = []byte{ 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9d, - 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x6f, 0x6b, 0x12, 0x17, 0x0a, 0x04, 0x69, 0x73, 0x62, 0x6e, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x04, 0x69, 0x73, 0x62, 0x6e, - 0x12, 0x19, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x42, - 0x03, 0xe0, 0x41, 0x02, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x09, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x42, 0x03, - 0xe0, 0x41, 0x02, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x18, - 0x0a, 0x07, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x07, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x13, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, - 0x18, 0x90, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x0f, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x91, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x7b, - 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x9d, 0x4e, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x00, 0x52, 0x06, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x12, 0x0f, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x9e, 0x4e, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x18, 0x9f, 0x4e, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, - 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x6b, - 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x22, 0x49, 0x0a, 0x0e, 0x47, - 0x65, 0x74, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, - 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0xa2, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x22, 0xe0, 0x41, - 0x02, 0xfa, 0x41, 0x1c, 0x0a, 0x1a, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, - 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6f, 0x6f, 0x6b, - 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0xc0, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, + 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9c, + 0x02, 0x0a, 0x04, 0x42, 0x6f, 0x6f, 0x6b, 0x12, 0x39, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, + 0x6f, 0x6f, 0x6b, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x12, 0x17, 0x0a, 0x04, 0x69, 0x73, 0x62, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, + 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x04, 0x69, 0x73, 0x62, 0x6e, 0x12, 0x19, 0x0a, 0x05, 0x70, + 0x72, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, + 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, + 0x68, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x09, + 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x64, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x65, 0x64, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x13, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x90, 0x4e, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x0f, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x91, + 0x4e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x1a, 0x42, 0x0a, 0x06, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x69, 0x72, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x72, 0x73, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x7b, 0x0a, + 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x9d, 0x4e, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x06, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x00, 0x52, 0x06, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x12, 0x0f, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x9e, 0x4e, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x18, 0x9f, 0x4e, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, + 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x6b, 0x42, + 0x03, 0xe0, 0x41, 0x02, 0x52, 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x22, 0x49, 0x0a, 0x0e, 0x47, 0x65, + 0x74, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0xa2, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x22, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x1c, 0x0a, 0x1a, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6f, 0x6f, 0x6b, 0x52, - 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x18, 0x9f, 0x4e, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, - 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x6b, - 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x12, 0x3c, 0x0a, 0x0b, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x9c, 0x4e, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x4c, 0x0a, 0x11, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, - 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0xa2, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x22, 0xe0, - 0x41, 0x02, 0xfa, 0x41, 0x1c, 0x0a, 0x1a, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, - 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6f, 0x6f, - 0x6b, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x77, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x42, - 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x06, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x18, 0x9d, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xe0, 0x41, 0x02, - 0xfa, 0x41, 0x00, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x70, - 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x9a, 0x4e, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x6d, - 0x61, 0x78, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0xa1, 0x4e, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x50, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, - 0x22, 0x72, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, - 0xa0, 0x4e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0xc0, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x70, + 0x61, 0x74, 0x68, 0x18, 0xa2, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x22, 0xe0, 0x41, 0x02, 0xfa, + 0x41, 0x1c, 0x0a, 0x1a, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x65, 0x78, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x04, + 0x70, 0x61, 0x74, 0x68, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x18, 0x9f, 0x4e, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, + 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x6b, 0x42, + 0x03, 0xe0, 0x41, 0x02, 0x52, 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x12, 0x3c, 0x0a, 0x0b, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x9c, 0x4e, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x4c, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0xa2, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x22, 0xe0, 0x41, + 0x02, 0xfa, 0x41, 0x1c, 0x0a, 0x1a, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, + 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6f, 0x6f, 0x6b, + 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x77, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6f, + 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x06, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x18, 0x9d, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xe0, 0x41, 0x02, 0xfa, + 0x41, 0x00, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, + 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x9a, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, + 0x78, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0xa1, 0x4e, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x50, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, + 0x72, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0xa0, + 0x4e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, + 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x6f, + 0x6b, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x65, + 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x9b, 0x4e, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x22, 0x81, 0x01, 0x0a, 0x10, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x42, 0x6f, 0x6f, + 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, + 0x18, 0xa2, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x22, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x1c, 0x0a, + 0x1a, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x04, 0x70, 0x61, 0x74, + 0x68, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x18, 0x9f, 0x4e, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x6b, 0x42, 0x03, 0xe0, 0x41, + 0x02, 0x52, 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x32, 0xda, 0x05, 0x0a, 0x09, 0x42, 0x6f, 0x6f, 0x6b, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x7e, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, + 0x6f, 0x6f, 0x6b, 0x12, 0x27, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, + 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x65, + 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x6b, 0x22, 0x2b, 0xda, 0x41, 0x0b, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x2c, 0x62, 0x6f, 0x6f, 0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, 0x04, + 0x62, 0x6f, 0x6f, 0x6b, 0x22, 0x0f, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x62, + 0x6f, 0x6f, 0x6b, 0x73, 0x7d, 0x12, 0x6b, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x6f, 0x6b, + 0x12, 0x24, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x6f, 0x6b, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, - 0x6f, 0x6b, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6e, - 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x9b, - 0x4e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x81, 0x01, 0x0a, 0x10, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x42, 0x6f, - 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x70, 0x61, 0x74, - 0x68, 0x18, 0xa2, 0x4e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x22, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x1c, - 0x0a, 0x1a, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x18, 0x9f, 0x4e, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, - 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x6b, 0x42, 0x03, 0xe0, - 0x41, 0x02, 0x52, 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x32, 0xda, 0x05, 0x0a, 0x09, 0x42, 0x6f, 0x6f, - 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x7e, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x42, 0x6f, 0x6f, 0x6b, 0x12, 0x27, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, - 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, - 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x6b, 0x22, 0x2b, 0xda, 0x41, 0x0b, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x2c, 0x62, 0x6f, 0x6f, 0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, - 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x22, 0x0f, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, - 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x7d, 0x12, 0x6b, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x6f, - 0x6b, 0x12, 0x24, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, - 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x6f, 0x6b, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, - 0x6f, 0x6f, 0x6b, 0x22, 0x1e, 0xda, 0x41, 0x04, 0x70, 0x61, 0x74, 0x68, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x7b, 0x70, 0x61, 0x74, 0x68, 0x3d, 0x62, 0x6f, 0x6f, 0x6b, 0x73, - 0x2f, 0x2a, 0x7d, 0x12, 0x83, 0x01, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x6f, - 0x6f, 0x6b, 0x12, 0x27, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, - 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x65, 0x78, - 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x6b, 0x22, 0x30, 0xda, 0x41, 0x10, 0x62, 0x6f, 0x6f, 0x6b, - 0x2c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x17, 0x3a, 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x32, 0x0f, 0x2f, 0x7b, 0x70, 0x61, 0x74, 0x68, - 0x3d, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x6d, 0x0a, 0x0a, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x42, 0x6f, 0x6f, 0x6b, 0x12, 0x27, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x1e, 0xda, 0x41, 0x04, 0x70, 0x61, 0x74, - 0x68, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x2a, 0x0f, 0x2f, 0x7b, 0x70, 0x61, 0x74, 0x68, 0x3d, - 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x7b, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, - 0x42, 0x6f, 0x6f, 0x6b, 0x12, 0x25, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, - 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x65, 0x78, - 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x20, 0xda, 0x41, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x62, - 0x6f, 0x6f, 0x6b, 0x73, 0x7d, 0x12, 0x6e, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x42, 0x6f, - 0x6f, 0x6b, 0x12, 0x26, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, - 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x42, + 0x6f, 0x6b, 0x22, 0x1e, 0xda, 0x41, 0x04, 0x70, 0x61, 0x74, 0x68, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x11, 0x12, 0x0f, 0x2f, 0x7b, 0x70, 0x61, 0x74, 0x68, 0x3d, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x2f, + 0x2a, 0x7d, 0x12, 0x83, 0x01, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x6f, 0x6f, + 0x6b, 0x12, 0x27, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x6b, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, 0x04, - 0x62, 0x6f, 0x6f, 0x6b, 0x1a, 0x0f, 0x2f, 0x7b, 0x70, 0x61, 0x74, 0x68, 0x3d, 0x62, 0x6f, 0x6f, - 0x6b, 0x73, 0x2f, 0x2a, 0x7d, 0x42, 0x0c, 0x5a, 0x0a, 0x2f, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, - 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x6b, 0x22, 0x30, 0xda, 0x41, 0x10, 0x62, 0x6f, 0x6f, 0x6b, 0x2c, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x17, 0x3a, 0x04, 0x62, 0x6f, 0x6f, 0x6b, 0x32, 0x0f, 0x2f, 0x7b, 0x70, 0x61, 0x74, 0x68, 0x3d, + 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x6d, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x42, 0x6f, 0x6f, 0x6b, 0x12, 0x27, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, + 0x2e, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x1e, 0xda, 0x41, 0x04, 0x70, 0x61, 0x74, 0x68, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x2a, 0x0f, 0x2f, 0x7b, 0x70, 0x61, 0x74, 0x68, 0x3d, 0x62, + 0x6f, 0x6f, 0x6b, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x7b, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x42, + 0x6f, 0x6f, 0x6b, 0x12, 0x25, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, + 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, + 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x20, 0xda, 0x41, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x62, 0x6f, + 0x6f, 0x6b, 0x73, 0x7d, 0x12, 0x6e, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x42, 0x6f, 0x6f, + 0x6b, 0x12, 0x26, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x42, 0x6f, + 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x65, 0x78, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x2e, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x42, 0x6f, 0x6f, 0x6b, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, 0x04, 0x62, + 0x6f, 0x6f, 0x6b, 0x1a, 0x0f, 0x2f, 0x7b, 0x70, 0x61, 0x74, 0x68, 0x3d, 0x62, 0x6f, 0x6f, 0x6b, + 0x73, 0x2f, 0x2a, 0x7d, 0x42, 0x0c, 0x5a, 0x0a, 0x2f, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x6f, + 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -674,7 +748,7 @@ func file_example_bookstore_v1_bookstore_proto_rawDescGZIP() []byte { return file_example_bookstore_v1_bookstore_proto_rawDescData } -var file_example_bookstore_v1_bookstore_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_example_bookstore_v1_bookstore_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_example_bookstore_v1_bookstore_proto_goTypes = []interface{}{ (*Book)(nil), // 0: example.bookstore.v1.Book (*CreateBookRequest)(nil), // 1: example.bookstore.v1.CreateBookRequest @@ -684,32 +758,34 @@ var file_example_bookstore_v1_bookstore_proto_goTypes = []interface{}{ (*ListBookRequest)(nil), // 5: example.bookstore.v1.ListBookRequest (*ListBookResponse)(nil), // 6: example.bookstore.v1.ListBookResponse (*ApplyBookRequest)(nil), // 7: example.bookstore.v1.ApplyBookRequest - (*fieldmaskpb.FieldMask)(nil), // 8: google.protobuf.FieldMask - (*emptypb.Empty)(nil), // 9: google.protobuf.Empty + (*Book_Author)(nil), // 8: example.bookstore.v1.Book.Author + (*fieldmaskpb.FieldMask)(nil), // 9: google.protobuf.FieldMask + (*emptypb.Empty)(nil), // 10: google.protobuf.Empty } var file_example_bookstore_v1_bookstore_proto_depIdxs = []int32{ - 0, // 0: example.bookstore.v1.CreateBookRequest.book:type_name -> example.bookstore.v1.Book - 0, // 1: example.bookstore.v1.UpdateBookRequest.book:type_name -> example.bookstore.v1.Book - 8, // 2: example.bookstore.v1.UpdateBookRequest.update_mask:type_name -> google.protobuf.FieldMask - 0, // 3: example.bookstore.v1.ListBookResponse.results:type_name -> example.bookstore.v1.Book - 0, // 4: example.bookstore.v1.ApplyBookRequest.book:type_name -> example.bookstore.v1.Book - 1, // 5: example.bookstore.v1.Bookstore.CreateBook:input_type -> example.bookstore.v1.CreateBookRequest - 2, // 6: example.bookstore.v1.Bookstore.GetBook:input_type -> example.bookstore.v1.GetBookRequest - 3, // 7: example.bookstore.v1.Bookstore.UpdateBook:input_type -> example.bookstore.v1.UpdateBookRequest - 4, // 8: example.bookstore.v1.Bookstore.DeleteBook:input_type -> example.bookstore.v1.DeleteBookRequest - 5, // 9: example.bookstore.v1.Bookstore.ListBook:input_type -> example.bookstore.v1.ListBookRequest - 7, // 10: example.bookstore.v1.Bookstore.ApplyBook:input_type -> example.bookstore.v1.ApplyBookRequest - 0, // 11: example.bookstore.v1.Bookstore.CreateBook:output_type -> example.bookstore.v1.Book - 0, // 12: example.bookstore.v1.Bookstore.GetBook:output_type -> example.bookstore.v1.Book - 0, // 13: example.bookstore.v1.Bookstore.UpdateBook:output_type -> example.bookstore.v1.Book - 9, // 14: example.bookstore.v1.Bookstore.DeleteBook:output_type -> google.protobuf.Empty - 6, // 15: example.bookstore.v1.Bookstore.ListBook:output_type -> example.bookstore.v1.ListBookResponse - 0, // 16: example.bookstore.v1.Bookstore.ApplyBook:output_type -> example.bookstore.v1.Book - 11, // [11:17] is the sub-list for method output_type - 5, // [5:11] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name + 8, // 0: example.bookstore.v1.Book.author:type_name -> example.bookstore.v1.Book.Author + 0, // 1: example.bookstore.v1.CreateBookRequest.book:type_name -> example.bookstore.v1.Book + 0, // 2: example.bookstore.v1.UpdateBookRequest.book:type_name -> example.bookstore.v1.Book + 9, // 3: example.bookstore.v1.UpdateBookRequest.update_mask:type_name -> google.protobuf.FieldMask + 0, // 4: example.bookstore.v1.ListBookResponse.results:type_name -> example.bookstore.v1.Book + 0, // 5: example.bookstore.v1.ApplyBookRequest.book:type_name -> example.bookstore.v1.Book + 1, // 6: example.bookstore.v1.Bookstore.CreateBook:input_type -> example.bookstore.v1.CreateBookRequest + 2, // 7: example.bookstore.v1.Bookstore.GetBook:input_type -> example.bookstore.v1.GetBookRequest + 3, // 8: example.bookstore.v1.Bookstore.UpdateBook:input_type -> example.bookstore.v1.UpdateBookRequest + 4, // 9: example.bookstore.v1.Bookstore.DeleteBook:input_type -> example.bookstore.v1.DeleteBookRequest + 5, // 10: example.bookstore.v1.Bookstore.ListBook:input_type -> example.bookstore.v1.ListBookRequest + 7, // 11: example.bookstore.v1.Bookstore.ApplyBook:input_type -> example.bookstore.v1.ApplyBookRequest + 0, // 12: example.bookstore.v1.Bookstore.CreateBook:output_type -> example.bookstore.v1.Book + 0, // 13: example.bookstore.v1.Bookstore.GetBook:output_type -> example.bookstore.v1.Book + 0, // 14: example.bookstore.v1.Bookstore.UpdateBook:output_type -> example.bookstore.v1.Book + 10, // 15: example.bookstore.v1.Bookstore.DeleteBook:output_type -> google.protobuf.Empty + 6, // 16: example.bookstore.v1.Bookstore.ListBook:output_type -> example.bookstore.v1.ListBookResponse + 0, // 17: example.bookstore.v1.Bookstore.ApplyBook:output_type -> example.bookstore.v1.Book + 12, // [12:18] is the sub-list for method output_type + 6, // [6:12] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_example_bookstore_v1_bookstore_proto_init() } @@ -814,6 +890,18 @@ func file_example_bookstore_v1_bookstore_proto_init() { return nil } } + file_example_bookstore_v1_bookstore_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Book_Author); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -821,7 +909,7 @@ func file_example_bookstore_v1_bookstore_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_example_bookstore_v1_bookstore_proto_rawDesc, NumEnums: 0, - NumMessages: 8, + NumMessages: 9, NumExtensions: 0, NumServices: 1, }, diff --git a/example/bookstore/v1/bookstore.proto b/example/bookstore/v1/bookstore.proto index 82fc563..c16d192 100644 --- a/example/bookstore/v1/bookstore.proto +++ b/example/bookstore/v1/bookstore.proto @@ -61,6 +61,17 @@ service Bookstore { // A Book resource. message Book { + message Author { + // Field for firstName. + string firstName = 1; + + // Field for lastName. + string lastName = 2; + } + + // Field for author. + repeated Author author = 5; + // Field for isbn. repeated string isbn = 1 [(google.api.field_behavior) = REQUIRED]; diff --git a/example/bookstore/v1/bookstore.swagger.json b/example/bookstore/v1/bookstore.swagger.json index b81661a..3220459 100644 --- a/example/bookstore/v1/bookstore.swagger.json +++ b/example/bookstore/v1/bookstore.swagger.json @@ -267,6 +267,19 @@ } }, "definitions": { + "BookAuthor": { + "type": "object", + "properties": { + "firstName": { + "type": "string", + "description": "Field for firstName." + }, + "lastName": { + "type": "string", + "description": "Field for lastName." + } + } + }, "protobufAny": { "type": "object", "properties": { @@ -298,6 +311,14 @@ "v1Book": { "type": "object", "properties": { + "author": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/BookAuthor" + }, + "description": "Field for author." + }, "isbn": { "type": "array", "items": { diff --git a/example/bookstore/v1/bookstore.yaml b/example/bookstore/v1/bookstore.yaml index 287f4e9..82fa88a 100644 --- a/example/bookstore/v1/bookstore.yaml +++ b/example/bookstore/v1/bookstore.yaml @@ -21,6 +21,16 @@ resources: type: INT32 number: 4 required: false + author: + array_type: + object_type: + properties: + firstName: + type: STRING + number: 1 + lastName: + type: STRING + number: 2 # parents: # - "bookstore.example.com/Publisher" methods: diff --git a/example/bookstore/v1/bookstore_openapi.json b/example/bookstore/v1/bookstore_openapi.json index 548f8d0..1bf2824 100644 --- a/example/bookstore/v1/bookstore_openapi.json +++ b/example/bookstore/v1/bookstore_openapi.json @@ -115,6 +115,12 @@ "published" ], "properties": { + "author": { + "type": "array", + "items": { + "type": "object" + } + }, "edition": { "type": "integer", "format": "int32" diff --git a/parser/parser.go b/parser/parser.go index ef358cd..efc3c25 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -57,16 +57,16 @@ func NewParsedService(s *schema.Service) (*ParsedService, error) { func ParsedResourceForObject(r *schema.Object, s *schema.Service) *ParsedResource { t := fmt.Sprintf("%s/%s", s.Name, r.Kind) return &ParsedResource{ - Type: t, - Resource: &schema.Resource{ - Kind: r.Kind, - Properties: r.Properties, - }, - IsResource: false, - } + Type: t, + Resource: &schema.Resource{ + Kind: r.Kind, + Properties: r.Properties, + }, + IsResource: false, + } } -func loadObjectsByType(o []*schema.Object, s *schema.Service, m *map[string]*ParsedResource) (error) { +func loadObjectsByType(o []*schema.Object, s *schema.Service, m *map[string]*ParsedResource) error { for _, r := range o { t := fmt.Sprintf("%s/%s", s.Name, r.Kind) (*m)[t] = ParsedResourceForObject(r, s) @@ -79,9 +79,9 @@ func loadResourceByType(s *schema.Service) (map[string]*ParsedResource, error) { for _, r := range s.Resources { t := fmt.Sprintf("%s/%s", s.Name, r.Kind) resourceByType[t] = &ParsedResource{ - Resource: r, - Type: t, - Parents: []*ParsedResource{}, + Resource: r, + Type: t, + Parents: []*ParsedResource{}, IsResource: true, } } @@ -106,10 +106,14 @@ func loadResourceByType(s *schema.Service) (map[string]*ParsedResource, error) { } func (pr *ParsedResource) GetPropertiesSortedByNumber() []*ParsedProperty { + return PropertiesSortedByNumber(pr.Properties) +} + +func PropertiesSortedByNumber(properties map[string]*schema.Property) []*ParsedProperty { // to ensure idempotency of generators, fields are ordered by // field number parsedProperties := []*ParsedProperty{} - for name, p := range pr.Properties { + for name, p := range properties { parsedProperties = append(parsedProperties, &ParsedProperty{ Property: p, Name: name, @@ -134,12 +138,12 @@ func addGetToResource(pr *ParsedResource) { // existence of path. func addCommonFieldsToResource(pr *ParsedResource) { pr.Properties[constants.FIELD_PATH_NAME] = &schema.Property{ - Types: &schema.Property_Type{Type: schema.Type_STRING}, + Types: &schema.Property_Type{Type: schema.Type_STRING}, Number: 10000, ReadOnly: true, } pr.Properties[constants.FIELD_ID_NAME] = &schema.Property{ - Types: &schema.Property_Type{Type: schema.Type_STRING}, + Types: &schema.Property_Type{Type: schema.Type_STRING}, Number: 10001, ReadOnly: true, } diff --git a/schema/resourcedefinition.pb.go b/schema/resourcedefinition.pb.go index d64dc52..29b9316 100644 --- a/schema/resourcedefinition.pb.go +++ b/schema/resourcedefinition.pb.go @@ -539,10 +539,9 @@ type ObjectType struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Types that are assignable to ObjectDetails: - // - // *ObjectType_MessageName - ObjectDetails isObjectType_ObjectDetails `protobuf_oneof:"object_details"` + // message_name and properties cannot both be set at the same time. + MessageName string `protobuf:"bytes,1,opt,name=message_name,json=messageName,proto3" json:"message_name,omitempty"` + Properties map[string]*Property `protobuf:"bytes,2,rep,name=properties,proto3" json:"properties,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *ObjectType) Reset() { @@ -577,30 +576,20 @@ func (*ObjectType) Descriptor() ([]byte, []int) { return file_schema_resourcedefinition_proto_rawDescGZIP(), []int{5} } -func (m *ObjectType) GetObjectDetails() isObjectType_ObjectDetails { - if m != nil { - return m.ObjectDetails - } - return nil -} - func (x *ObjectType) GetMessageName() string { - if x, ok := x.GetObjectDetails().(*ObjectType_MessageName); ok { + if x != nil { return x.MessageName } return "" } -type isObjectType_ObjectDetails interface { - isObjectType_ObjectDetails() -} - -type ObjectType_MessageName struct { - MessageName string `protobuf:"bytes,1,opt,name=message_name,json=messageName,proto3,oneof"` +func (x *ObjectType) GetProperties() map[string]*Property { + if x != nil { + return x.Properties + } + return nil } -func (*ObjectType_MessageName) isObjectType_ObjectDetails() {} - type ArrayType struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1034,26 +1023,33 @@ var file_schema_resourcedefinition_proto_rawDesc = []byte{ 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x22, 0x43, 0x0a, 0x0a, - 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x42, - 0x10, 0x0a, 0x0e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, - 0x73, 0x22, 0x69, 0x0a, 0x09, 0x41, 0x72, 0x72, 0x61, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x05, 0x2e, 0x54, - 0x79, 0x70, 0x65, 0x48, 0x00, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2e, 0x0a, 0x0b, 0x6f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0b, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x48, 0x00, 0x52, - 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x42, 0x0f, 0x0a, 0x0d, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2a, 0x62, 0x0a, 0x04, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, - 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, - 0x02, 0x12, 0x09, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, - 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x4c, 0x4f, 0x41, - 0x54, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x42, 0x4f, 0x4f, 0x4c, 0x45, 0x41, 0x4e, 0x10, 0x06, - 0x42, 0x09, 0x5a, 0x07, 0x2f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x72, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x22, 0xb6, 0x01, 0x0a, + 0x0a, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3b, + 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x2e, + 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x1a, 0x48, 0x0a, 0x0f, 0x50, + 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x1f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x09, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x69, 0x0a, 0x09, 0x41, 0x72, 0x72, 0x61, 0x79, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x05, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x48, 0x00, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, + 0x2e, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x48, 0x00, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x42, + 0x0f, 0x0a, 0x0d, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, + 0x2a, 0x5d, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, + 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x02, + 0x12, 0x09, 0x0a, 0x05, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x44, + 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x4c, 0x4f, 0x41, 0x54, + 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x42, 0x4f, 0x4f, 0x4c, 0x45, 0x41, 0x4e, 0x10, 0x06, 0x42, + 0x09, 0x5a, 0x07, 0x2f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -1069,7 +1065,7 @@ func file_schema_resourcedefinition_proto_rawDescGZIP() []byte { } var file_schema_resourcedefinition_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_schema_resourcedefinition_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_schema_resourcedefinition_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_schema_resourcedefinition_proto_goTypes = []interface{}{ (Type)(0), // 0: Type (*Service)(nil), // 1: Service @@ -1088,6 +1084,7 @@ var file_schema_resourcedefinition_proto_goTypes = []interface{}{ (*Methods_ListMethod)(nil), // 14: Methods.ListMethod (*Methods_GlobalListMethod)(nil), // 15: Methods.GlobalListMethod (*Methods_ApplyMethod)(nil), // 16: Methods.ApplyMethod + nil, // 17: ObjectType.PropertiesEntry } var file_schema_resourcedefinition_proto_depIdxs = []int32{ 2, // 0: Service.resources:type_name -> Resource @@ -1105,15 +1102,17 @@ var file_schema_resourcedefinition_proto_depIdxs = []int32{ 0, // 12: Property.type:type_name -> Type 6, // 13: Property.object_type:type_name -> ObjectType 7, // 14: Property.array_type:type_name -> ArrayType - 0, // 15: ArrayType.type:type_name -> Type - 6, // 16: ArrayType.object_type:type_name -> ObjectType - 5, // 17: Resource.PropertiesEntry.value:type_name -> Property - 5, // 18: Object.PropertiesEntry.value:type_name -> Property - 19, // [19:19] is the sub-list for method output_type - 19, // [19:19] is the sub-list for method input_type - 19, // [19:19] is the sub-list for extension type_name - 19, // [19:19] is the sub-list for extension extendee - 0, // [0:19] is the sub-list for field type_name + 17, // 15: ObjectType.properties:type_name -> ObjectType.PropertiesEntry + 0, // 16: ArrayType.type:type_name -> Type + 6, // 17: ArrayType.object_type:type_name -> ObjectType + 5, // 18: Resource.PropertiesEntry.value:type_name -> Property + 5, // 19: Object.PropertiesEntry.value:type_name -> Property + 5, // 20: ObjectType.PropertiesEntry.value:type_name -> Property + 21, // [21:21] is the sub-list for method output_type + 21, // [21:21] is the sub-list for method input_type + 21, // [21:21] is the sub-list for extension type_name + 21, // [21:21] is the sub-list for extension extendee + 0, // [0:21] is the sub-list for field type_name } func init() { file_schema_resourcedefinition_proto_init() } @@ -1296,9 +1295,6 @@ func file_schema_resourcedefinition_proto_init() { (*Property_ObjectType)(nil), (*Property_ArrayType)(nil), } - file_schema_resourcedefinition_proto_msgTypes[5].OneofWrappers = []interface{}{ - (*ObjectType_MessageName)(nil), - } file_schema_resourcedefinition_proto_msgTypes[6].OneofWrappers = []interface{}{ (*ArrayType_Type)(nil), (*ArrayType_ObjectType)(nil), @@ -1309,7 +1305,7 @@ func file_schema_resourcedefinition_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_schema_resourcedefinition_proto_rawDesc, NumEnums: 1, - NumMessages: 16, + NumMessages: 17, NumExtensions: 0, NumServices: 0, }, diff --git a/schema/resourcedefinition.proto b/schema/resourcedefinition.proto index 65b77ac..9d17215 100644 --- a/schema/resourcedefinition.proto +++ b/schema/resourcedefinition.proto @@ -92,9 +92,9 @@ message Property { } message ObjectType { - oneof object_details { - string message_name = 1; - } + // message_name and properties cannot both be set at the same time. + string message_name = 1; + map properties = 2; } message ArrayType { diff --git a/validator/validator.go b/validator/validator.go index 6ac24cc..24eff00 100644 --- a/validator/validator.go +++ b/validator/validator.go @@ -44,5 +44,23 @@ func validateResource(r *schema.Resource) []error { fmt.Errorf("kind must match regex %q", RESOURCE_KIND_REGEX_STRING), ) } + + for _, p := range r.Properties { + errors = append(errors, validateProperty(p)...) + } + return errors +} + +func validateProperty(p *schema.Property) []error { + errors := []error{} + switch p.GetTypes().(type) { + case *schema.Property_ObjectType: + if p.GetObjectType().GetMessageName() != "" && len(p.GetObjectType().GetProperties()) != 0 { + errors = append(errors, fmt.Errorf("cannot set both message_name and properties on object_type %q", p)) + } + for _, p := range p.GetObjectType().GetProperties() { + errors = append(errors, validateProperty(p)...) + } + } return errors } diff --git a/writer/openapi/openapi.go b/writer/openapi/openapi.go index 151f529..563c96b 100644 --- a/writer/openapi/openapi.go +++ b/writer/openapi/openapi.go @@ -39,9 +39,9 @@ func convertToOpenAPI(service *parser.ParsedService) (*OpenAPI, error) { if err != nil { return nil, err } - definitions[r.Kind] = d; - if(!r.IsResource) { - continue; + definitions[r.Kind] = d + if !r.IsResource { + continue } schemaRef := fmt.Sprintf("#/definitions/%v", r.Kind) if r.Methods.List != nil { @@ -167,13 +167,13 @@ func convertToOpenAPI(service *parser.ParsedService) (*OpenAPI, error) { return openAPI, nil } -func resourceToSchema(r *parser.ParsedResource) (Schema, error) { +func buildProperties(props []*parser.ParsedProperty) (Properties, []string, error) { properties := Properties{} required := []string{} - for _, f := range r.GetPropertiesSortedByNumber() { + for _, f := range props { t, err := openAPIType(f.Property) if err != nil { - return Schema{}, err + return Properties{}, []string{}, err } s := Schema{ Type: t.openapi_type, @@ -186,14 +186,47 @@ func resourceToSchema(r *parser.ParsedResource) (Schema, error) { required = append(required, f.Name) } switch f.GetTypes().(type) { - case *schema.Property_ArrayType: + case *schema.Property_ArrayType: + switch f.GetArrayType().GetArrayDetails().(type) { + case *schema.ArrayType_ObjectType: + s.Items = &Schema{ + Type: t.array_type.openapi_type, + Format: t.array_type.openapi_format, + } + if len(f.GetObjectType().GetProperties()) > 0 { + props, required, err := buildProperties(parser.PropertiesSortedByNumber(f.GetObjectType().GetProperties())) + if err != nil { + return Properties{}, []string{}, err + } + s.Items.Required = required + s.Items.Properties = &props + } + case *schema.ArrayType_Type: s.Items = &Schema{ - Type: t.array_type.openapi_type, + Type: t.array_type.openapi_type, Format: t.array_type.openapi_format, } + } + case *schema.Property_ObjectType: + if len(f.GetObjectType().GetProperties()) > 0 { + props, required, err := buildProperties(parser.PropertiesSortedByNumber(f.GetObjectType().GetProperties())) + if err != nil { + return Properties{}, []string{}, err + } + s.Required = required + s.Properties = &props + } } properties[f.Name] = s } + return properties, required, nil +} + +func resourceToSchema(r *parser.ParsedResource) (Schema, error) { + properties, required, err := buildProperties(r.GetPropertiesSortedByNumber()) + if err != nil { + return Schema{}, err + } return Schema{ Type: "object", Properties: &properties, diff --git a/writer/openapi/utils.go b/writer/openapi/utils.go index 8ed47ad..06aabd1 100644 --- a/writer/openapi/utils.go +++ b/writer/openapi/utils.go @@ -7,79 +7,85 @@ import ( ) type TypeInfo struct { - openapi_type string - openapi_format string - openapi_ref string + openapi_type string + openapi_format string + openapi_ref string - array_type *TypeInfo + array_type *TypeInfo } func openAPIType(p *schema.Property) (TypeInfo, error) { switch p.GetTypes().(type) { - case *schema.Property_ArrayType: - return openAPITypeArray(p.GetArrayType()) - case *schema.Property_ObjectType: - return openAPITypeObject(p.GetObjectType()) - case *schema.Property_Type: - return openAPITypePrimitive(p.GetType()) - default: - return TypeInfo{}, fmt.Errorf("openapi type for %q not found", p.GetTypes()) + case *schema.Property_ArrayType: + return openAPITypeArray(p.GetArrayType()) + case *schema.Property_ObjectType: + return openAPITypeObject(p.GetObjectType()) + case *schema.Property_Type: + return openAPITypePrimitive(p.GetType()) + default: + return TypeInfo{}, fmt.Errorf("openapi type for %q not found", p.GetTypes()) } } func openAPITypeArray(a *schema.ArrayType) (TypeInfo, error) { switch a.GetArrayDetails().(type) { - case *schema.ArrayType_Type: - at, err := openAPITypePrimitive(a.GetType()) - if(err != nil) { - return TypeInfo{}, err - } - return TypeInfo{ - openapi_type: "array", - array_type: &at, - }, nil - case *schema.ArrayType_ObjectType: - ot, err := openAPITypeObject(a.GetObjectType()) - if(err != nil) { - return TypeInfo{}, nil - } - ot.openapi_type = "array" - return ot, nil - - default: - return TypeInfo{} , fmt.Errorf("OpenAPI type for %q not found", a.GetArrayDetails()) + case *schema.ArrayType_Type: + at, err := openAPITypePrimitive(a.GetType()) + if err != nil { + return TypeInfo{}, err + } + return TypeInfo{ + openapi_type: "array", + array_type: &at, + }, nil + case *schema.ArrayType_ObjectType: + ot, err := openAPITypeObject(a.GetObjectType()) + if err != nil { + return TypeInfo{}, err + } + return TypeInfo{ + openapi_type: "array", + array_type: &ot, + }, nil + + default: + return TypeInfo{}, fmt.Errorf("OpenAPI type for %q not found", a.GetArrayDetails()) } } func openAPITypeObject(o *schema.ObjectType) (TypeInfo, error) { - return TypeInfo{ - openapi_ref: fmt.Sprintf("#/components/schemas/%s", o.GetMessageName()), - }, nil + if o.GetMessageName() != "" { + return TypeInfo{ + openapi_ref: fmt.Sprintf("#/components/schemas/%s", o.GetMessageName()), + }, nil + } else { + return TypeInfo{openapi_type: "object"}, nil + } } func openAPITypePrimitive(p schema.Type) (TypeInfo, error) { - t := ""; - f := ""; + t := "" + f := "" - switch(p) { - case schema.Type_STRING: - t = "string" - case schema.Type_DOUBLE: - t = "number" - f = "double" - case schema.Type_FLOAT: - t = "number" - f = "float" - case schema.Type_INT32: - t = "integer" - f = "int32" - case schema.Type_INT64: - t = "integer" - f = "int64" - case schema.Type_BOOLEAN: - t = "boolean" - default: - return TypeInfo{}, fmt.Errorf("%s does not have openapi type support", p.Type) + switch p { + case schema.Type_STRING: + t = "string" + case schema.Type_DOUBLE: + t = "number" + f = "double" + case schema.Type_FLOAT: + t = "number" + f = "float" + case schema.Type_INT32: + t = "integer" + f = "int32" + case schema.Type_INT64: + t = "integer" + f = "int64" + case schema.Type_BOOLEAN: + t = "boolean" + default: + return TypeInfo{}, fmt.Errorf("%s does not have openapi type support", p.Type) } return TypeInfo{ diff --git a/writer/proto/proto.go b/writer/proto/proto.go index bb1f537..34b0908 100644 --- a/writer/proto/proto.go +++ b/writer/proto/proto.go @@ -72,7 +72,7 @@ func WriteServiceToProto(ps *parser.ParsedService, outputDir string) ([]byte, er // Add resources to MessageStorage. err := GenerateResourceMessages(ps.ResourceByType, ps, m) - if(err != nil) { + if err != nil { return nil, err } @@ -108,11 +108,11 @@ func WriteServiceToProto(ps *parser.ParsedService, outputDir string) ([]byte, er return output.Bytes(), nil } -func GenerateResourceMessages(r map[string]*parser.ParsedResource, s *parser.ParsedService, m *MessageStorage) (error) { +func GenerateResourceMessages(r map[string]*parser.ParsedResource, s *parser.ParsedService, m *MessageStorage) error { // Generate Resource messages on combined map for _, r := range getSortedResources(r) { _, err := GeneratedResourceMessage(r, s, m) - if(err != nil) { + if err != nil { return err } } @@ -124,6 +124,10 @@ func toProtoServiceName(serviceName string) string { return capitalizer.String(parts[0]) } +func toMessageName(resource string) string { + return capitalizer.String(resource) +} + func getSortedResources(prsByString map[string]*parser.ParsedResource) []*parser.ParsedResource { keys := []string{} for k := range prsByString { diff --git a/writer/proto/resource.go b/writer/proto/resource.go index d0f6966..ec70750 100644 --- a/writer/proto/resource.go +++ b/writer/proto/resource.go @@ -43,8 +43,8 @@ func AddResource(r *parser.ParsedResource, ps *parser.ParsedService, fb *builder }) fb.AddMessage(resourceMb) - if(!r.IsResource) { - return nil; + if !r.IsResource { + return nil } if r.Methods != nil { @@ -95,104 +95,120 @@ func AddResource(r *parser.ParsedResource, ps *parser.ParsedService, fb *builder return nil } -func protoType(p *parser.ParsedProperty, s *parser.ParsedService, m *MessageStorage) (*builder.FieldType, error) { +func protoType(p *parser.ParsedProperty, s *parser.ParsedService, m *MessageStorage, parent *builder.MessageBuilder) (*builder.FieldType, error) { switch p.GetTypes().(type) { - case *schema.Property_Type: - return protoTypePrimitive(p.GetType()) - case *schema.Property_ObjectType: - return protoTypeObject(p.GetObjectType(), s, m) - case *schema.Property_ArrayType: - return protoTypeArray(p.GetArrayType(), s, m) - default: - return nil, fmt.Errorf("reached outside of prototype switch statement.") + case *schema.Property_Type: + return protoTypePrimitive(p.GetType()) + case *schema.Property_ObjectType: + return protoTypeObject(p.GetObjectType(), p, s, m, parent) + case *schema.Property_ArrayType: + return protoTypeArray(p.GetArrayType(), p, s, m, parent) + default: + return nil, fmt.Errorf("reached outside of prototype switch statement.") } } -func protoTypeObject(o *schema.ObjectType, s *parser.ParsedService, m *MessageStorage) (*builder.FieldType, error) { - wantedType := fmt.Sprintf("%s/%s", s.Name, o.GetMessageName()) - _, ok := m.Messages[wantedType] - if(!ok) { - // Resource has not been generated yet. - n, ok := s.ResourceByType[wantedType] - if(!ok) { - return nil, fmt.Errorf("could not find %s in full object list", wantedType) +func protoTypeObject(o *schema.ObjectType, p *parser.ParsedProperty, s *parser.ParsedService, m *MessageStorage, parent *builder.MessageBuilder) (*builder.FieldType, error) { + if o.GetMessageName() != "" { + wantedType := fmt.Sprintf("%s/%s", s.Name, o.GetMessageName()) + _, ok := m.Messages[wantedType] + if !ok { + // Resource has not been generated yet. + n, ok := s.ResourceByType[wantedType] + if !ok { + return nil, fmt.Errorf("could not find %s in full object list", wantedType) + } + _, err := GeneratedResourceMessage(n, s, m) + if err != nil { + return nil, err + } } - _, err := GeneratedResourceMessage(n, s, m) - if (err != nil) { - return nil, err; + resourceMb, ok := m.Messages[wantedType] + if !ok { + return nil, fmt.Errorf("could not find message %s after recursive create", wantedType) } + return builder.FieldTypeMessage(resourceMb), nil + } else { + msg, err := GenerateMessage(parser.PropertiesSortedByNumber(o.GetProperties()), toMessageName(p.Name), s, m) + if err != nil { + return nil, err + } + parent.AddNestedMessage(msg) + return builder.FieldTypeMessage(msg), nil } - resourceMb, ok := m.Messages[wantedType] - if(!ok) { - return nil, fmt.Errorf("could not find message %s after recursive create", wantedType) - } - return builder.FieldTypeMessage(resourceMb), nil } -func protoTypeArray(a *schema.ArrayType, s *parser.ParsedService, m *MessageStorage) (*builder.FieldType, error) { +func protoTypeArray(a *schema.ArrayType, p *parser.ParsedProperty, s *parser.ParsedService, m *MessageStorage, parent *builder.MessageBuilder) (*builder.FieldType, error) { switch a.GetArrayDetails().(type) { - case *schema.ArrayType_Type: - // Repeated will be set later on. - return protoTypePrimitive(a.GetType()) - case *schema.ArrayType_ObjectType: - return protoTypeObject(a.GetObjectType(), s, m) - default: - return nil, fmt.Errorf("Proto type for %q not found ", a) + case *schema.ArrayType_Type: + // Repeated will be set later on. + return protoTypePrimitive(a.GetType()) + case *schema.ArrayType_ObjectType: + return protoTypeObject(a.GetObjectType(), p, s, m, parent) + default: + return nil, fmt.Errorf("Proto type for %q not found ", a) } } func protoTypePrimitive(t schema.Type) (*builder.FieldType, error) { - switch t { - case schema.Type_STRING: - return builder.FieldTypeString(), nil - case schema.Type_INT32: - return builder.FieldTypeInt32(), nil - case schema.Type_INT64: - return builder.FieldTypeInt64(), nil - case schema.Type_BOOLEAN: - return builder.FieldTypeBool(), nil - case schema.Type_DOUBLE: - return builder.FieldTypeDouble(), nil - case schema.Type_FLOAT: - return builder.FieldTypeFloat(), nil - default: - return nil, fmt.Errorf("Proto type for %q not found", t) - } + switch t { + case schema.Type_STRING: + return builder.FieldTypeString(), nil + case schema.Type_INT32: + return builder.FieldTypeInt32(), nil + case schema.Type_INT64: + return builder.FieldTypeInt64(), nil + case schema.Type_BOOLEAN: + return builder.FieldTypeBool(), nil + case schema.Type_DOUBLE: + return builder.FieldTypeDouble(), nil + case schema.Type_FLOAT: + return builder.FieldTypeFloat(), nil + default: + return nil, fmt.Errorf("Proto type for %q not found", t) + } } -func protoField(p *parser.ParsedProperty, s *parser.ParsedService, m *MessageStorage) (*builder.FieldBuilder, error) { - typ, err := protoType(p, s, m) - if(err != nil) { - return nil, err - } +func protoField(p *parser.ParsedProperty, s *parser.ParsedService, m *MessageStorage, parent *builder.MessageBuilder) (*builder.FieldBuilder, error) { + typ, err := protoType(p, s, m, parent) + if err != nil { + return nil, err + } f := builder.NewField(p.Name, typ).SetNumber(p.Number).SetComments( builder.Comments{ LeadingComment: fmt.Sprintf("Field for %v.", p.Name), }, ) switch p.GetTypes().(type) { - case *schema.Property_ArrayType: - f.SetRepeated(); + case *schema.Property_ArrayType: + f.SetRepeated() } o := &descriptorpb.FieldOptions{} - if(p.Required) { + if p.Required { proto.SetExtension(o, annotations.E_FieldBehavior, []annotations.FieldBehavior{annotations.FieldBehavior_REQUIRED}) } f.SetOptions(o) return f, nil } -// GenerateResourceMesssage adds the resource message. -func GeneratedResourceMessage(r *parser.ParsedResource, s *parser.ParsedService, m *MessageStorage) (*builder.MessageBuilder, error) { - mb := builder.NewMessage(r.Kind) - for _, p := range r.GetPropertiesSortedByNumber() { - f, err := protoField(p, s, m) - if(err != nil) { +func GenerateMessage(properties []*parser.ParsedProperty, name string, s *parser.ParsedService, m *MessageStorage) (*builder.MessageBuilder, error) { + mb := builder.NewMessage(name) + for _, p := range properties { + f, err := protoField(p, s, m, mb) + if err != nil { return nil, err } - mb.AddField(f) } + return mb, nil +} + +// GenerateResourceMesssage adds the resource message. +func GeneratedResourceMessage(r *parser.ParsedResource, s *parser.ParsedService, m *MessageStorage) (*builder.MessageBuilder, error) { + mb, err := GenerateMessage(r.GetPropertiesSortedByNumber(), r.Kind, s, m) + if err != nil { + return nil, err + } m.Messages[fmt.Sprintf("%s/%s", s.Name, r.Kind)] = mb return mb, nil }