diff --git a/api/graphql.proto b/api/graphql.proto new file mode 100644 index 0000000..1a17d2d --- /dev/null +++ b/api/graphql.proto @@ -0,0 +1,138 @@ +// Copyright 2021 Edward McFarlane. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +syntax = "proto3"; + +package larking.api; + +import "google/api/annotations.proto"; +import "google/protobuf/any.proto"; +import "google/protobuf/descriptor.proto"; +import "google/protobuf/struct.proto"; + +option go_package = "larking.io/api/graphqlpb;graphqlpb"; + +// Relay GraphQL implementation +// https://relay.dev/docs/guides/graphql-server-specification/ +// http://spec.graphql.org/draft/ +// +// Cursor implementation +// https://relay.dev/assets/files/connections-932f4f2cdffd79724ac76373deb30dc8.htm# + +extend google.protobuf.MethodOptions { + // Adds a method to the GraphQL query root. + Rule graphql = 72222228; +} + +extend google.protobuf.FieldOptions { + // Adds relay + optional bool relay_id = 70000; +} + +// Rule implements GraphQL bindings. +message Rule { + oneof pattern { + string query = 1; + string mutation = 2; + string subscription = 3; + } + + // Args is a mapping of fields. + repeated Arg args = 4; + + // Controls the Relay NodeID binding. + string node_id = 5; + + // Additional GraphQL bindings for the selector. Nested bindings must + // not contain an `additional_bindings` field themselves (that is, + // the nesting may only be one level deep). + repeated Rule additional_bindings = 6; +} + +extend google.protobuf.MessageOptions { Edge edge = 70001; } + +message Edge { + string name = 1; + string method = 2; +} + +extend google.protobuf.MessageOptions { MessageConnection connection = 70002; } + +message Arg { + string name = 1; + string field = 2; +} + +// Connection +// https://relay.dev/graphql/connections.htm# +// A field that returns a Connection Type must include forward pagination +// arguments, backward pagination arguments, or both. These pagination arguments +// allow the client to slice the set of edges before it is returned. +// +// Forward Arguments: +// - first takes a non-negative integer. +// - after takes the cursor type as described in the cursor field section. +// +// Backward Arguments: +// - last takes a non-negative integer. +// - before takes the cursor type as described in the cursor field section. +message MessageConnection { + // TODO + string name = 1; + string method = 2; + repeated Arg args = 3; +} + +// https://relay.dev/graphql/connections.htm +message PageInfo { + bool has_next_page = 1; + bool has_previous_page = 2; + bytes start_cursor = 3; + bytes end_cursor = 4; +} + +message Connection { + repeated google.protobuf.Any edges = 1; + PageInfo page_info = 2; +} + +message Request { + string query = 1; + string operation_name = 2; + google.protobuf.Struct variables = 3; +} + +message Response { + google.protobuf.Struct data = 1; + repeated Error errors = 2; +} + +message SourceLocation { + int32 line = 1; + int32 column = 2; +} + +message Error { + string message = 1; + repeated SourceLocation locations = 2; + repeated string path = 3; +} + +service GraphQL { + rpc Query(Request) returns (Response) { + option (google.api.http) = { + post : "/graphql" + additional_bindings {get : "/graphql"} + }; + } + // TODO: Subscriptions +} + +// message GetRelayNodeRequest { string id = 1; } +// +//// Relay service is a client required service for GraphQL options. +// service Relay { +// // GetRelayNode exposes ID! querying capabilities to the GraphQL service. +// rpc GetRelayNode(GetRelayNodeRequest) returns (google.protobuf.Any); +// } diff --git a/api/graphqlpb/graphql.pb.go b/api/graphqlpb/graphql.pb.go new file mode 100644 index 0000000..a54a24f --- /dev/null +++ b/api/graphqlpb/graphql.pb.go @@ -0,0 +1,1086 @@ +// Copyright 2021 Edward McFarlane. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc v3.21.12 +// source: larking/api/graphql.proto + +package graphqlpb + +import ( + _ "google.golang.org/genproto/googleapis/api/annotations" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + descriptorpb "google.golang.org/protobuf/types/descriptorpb" + anypb "google.golang.org/protobuf/types/known/anypb" + structpb "google.golang.org/protobuf/types/known/structpb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Rule implements GraphQL bindings. +type Rule struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Pattern: + // + // *Rule_Query + // *Rule_Mutation + // *Rule_Subscription + Pattern isRule_Pattern `protobuf_oneof:"pattern"` + // Args is a mapping of fields. + Args []*Arg `protobuf:"bytes,4,rep,name=args,proto3" json:"args,omitempty"` + // Controls the Relay NodeID binding. + NodeId string `protobuf:"bytes,5,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + // Additional GraphQL bindings for the selector. Nested bindings must + // not contain an `additional_bindings` field themselves (that is, + // the nesting may only be one level deep). + AdditionalBindings []*Rule `protobuf:"bytes,6,rep,name=additional_bindings,json=additionalBindings,proto3" json:"additional_bindings,omitempty"` +} + +func (x *Rule) Reset() { + *x = Rule{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_graphql_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Rule) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Rule) ProtoMessage() {} + +func (x *Rule) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_graphql_proto_msgTypes[0] + 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 Rule.ProtoReflect.Descriptor instead. +func (*Rule) Descriptor() ([]byte, []int) { + return file_larking_api_graphql_proto_rawDescGZIP(), []int{0} +} + +func (m *Rule) GetPattern() isRule_Pattern { + if m != nil { + return m.Pattern + } + return nil +} + +func (x *Rule) GetQuery() string { + if x, ok := x.GetPattern().(*Rule_Query); ok { + return x.Query + } + return "" +} + +func (x *Rule) GetMutation() string { + if x, ok := x.GetPattern().(*Rule_Mutation); ok { + return x.Mutation + } + return "" +} + +func (x *Rule) GetSubscription() string { + if x, ok := x.GetPattern().(*Rule_Subscription); ok { + return x.Subscription + } + return "" +} + +func (x *Rule) GetArgs() []*Arg { + if x != nil { + return x.Args + } + return nil +} + +func (x *Rule) GetNodeId() string { + if x != nil { + return x.NodeId + } + return "" +} + +func (x *Rule) GetAdditionalBindings() []*Rule { + if x != nil { + return x.AdditionalBindings + } + return nil +} + +type isRule_Pattern interface { + isRule_Pattern() +} + +type Rule_Query struct { + Query string `protobuf:"bytes,1,opt,name=query,proto3,oneof"` +} + +type Rule_Mutation struct { + Mutation string `protobuf:"bytes,2,opt,name=mutation,proto3,oneof"` +} + +type Rule_Subscription struct { + Subscription string `protobuf:"bytes,3,opt,name=subscription,proto3,oneof"` +} + +func (*Rule_Query) isRule_Pattern() {} + +func (*Rule_Mutation) isRule_Pattern() {} + +func (*Rule_Subscription) isRule_Pattern() {} + +type Edge struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"` +} + +func (x *Edge) Reset() { + *x = Edge{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_graphql_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Edge) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Edge) ProtoMessage() {} + +func (x *Edge) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_graphql_proto_msgTypes[1] + 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 Edge.ProtoReflect.Descriptor instead. +func (*Edge) Descriptor() ([]byte, []int) { + return file_larking_api_graphql_proto_rawDescGZIP(), []int{1} +} + +func (x *Edge) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Edge) GetMethod() string { + if x != nil { + return x.Method + } + return "" +} + +type Arg struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Field string `protobuf:"bytes,2,opt,name=field,proto3" json:"field,omitempty"` +} + +func (x *Arg) Reset() { + *x = Arg{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_graphql_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Arg) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Arg) ProtoMessage() {} + +func (x *Arg) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_graphql_proto_msgTypes[2] + 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 Arg.ProtoReflect.Descriptor instead. +func (*Arg) Descriptor() ([]byte, []int) { + return file_larking_api_graphql_proto_rawDescGZIP(), []int{2} +} + +func (x *Arg) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Arg) GetField() string { + if x != nil { + return x.Field + } + return "" +} + +// Connection +// https://relay.dev/graphql/connections.htm# +// A field that returns a Connection Type must include forward pagination +// arguments, backward pagination arguments, or both. These pagination arguments +// allow the client to slice the set of edges before it is returned. +// +// Forward Arguments: +// - first takes a non-negative integer. +// - after takes the cursor type as described in the cursor field section. +// +// Backward Arguments: +// - last takes a non-negative integer. +// - before takes the cursor type as described in the cursor field section. +type MessageConnection struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // TODO + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"` + Args []*Arg `protobuf:"bytes,3,rep,name=args,proto3" json:"args,omitempty"` +} + +func (x *MessageConnection) Reset() { + *x = MessageConnection{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_graphql_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MessageConnection) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MessageConnection) ProtoMessage() {} + +func (x *MessageConnection) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_graphql_proto_msgTypes[3] + 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 MessageConnection.ProtoReflect.Descriptor instead. +func (*MessageConnection) Descriptor() ([]byte, []int) { + return file_larking_api_graphql_proto_rawDescGZIP(), []int{3} +} + +func (x *MessageConnection) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *MessageConnection) GetMethod() string { + if x != nil { + return x.Method + } + return "" +} + +func (x *MessageConnection) GetArgs() []*Arg { + if x != nil { + return x.Args + } + return nil +} + +// https://relay.dev/graphql/connections.htm +type PageInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + HasNextPage bool `protobuf:"varint,1,opt,name=has_next_page,json=hasNextPage,proto3" json:"has_next_page,omitempty"` + HasPreviousPage bool `protobuf:"varint,2,opt,name=has_previous_page,json=hasPreviousPage,proto3" json:"has_previous_page,omitempty"` + StartCursor []byte `protobuf:"bytes,3,opt,name=start_cursor,json=startCursor,proto3" json:"start_cursor,omitempty"` + EndCursor []byte `protobuf:"bytes,4,opt,name=end_cursor,json=endCursor,proto3" json:"end_cursor,omitempty"` +} + +func (x *PageInfo) Reset() { + *x = PageInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_graphql_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PageInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PageInfo) ProtoMessage() {} + +func (x *PageInfo) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_graphql_proto_msgTypes[4] + 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 PageInfo.ProtoReflect.Descriptor instead. +func (*PageInfo) Descriptor() ([]byte, []int) { + return file_larking_api_graphql_proto_rawDescGZIP(), []int{4} +} + +func (x *PageInfo) GetHasNextPage() bool { + if x != nil { + return x.HasNextPage + } + return false +} + +func (x *PageInfo) GetHasPreviousPage() bool { + if x != nil { + return x.HasPreviousPage + } + return false +} + +func (x *PageInfo) GetStartCursor() []byte { + if x != nil { + return x.StartCursor + } + return nil +} + +func (x *PageInfo) GetEndCursor() []byte { + if x != nil { + return x.EndCursor + } + return nil +} + +type Connection struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Edges []*anypb.Any `protobuf:"bytes,1,rep,name=edges,proto3" json:"edges,omitempty"` + PageInfo *PageInfo `protobuf:"bytes,2,opt,name=page_info,json=pageInfo,proto3" json:"page_info,omitempty"` +} + +func (x *Connection) Reset() { + *x = Connection{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_graphql_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Connection) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Connection) ProtoMessage() {} + +func (x *Connection) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_graphql_proto_msgTypes[5] + 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 Connection.ProtoReflect.Descriptor instead. +func (*Connection) Descriptor() ([]byte, []int) { + return file_larking_api_graphql_proto_rawDescGZIP(), []int{5} +} + +func (x *Connection) GetEdges() []*anypb.Any { + if x != nil { + return x.Edges + } + return nil +} + +func (x *Connection) GetPageInfo() *PageInfo { + if x != nil { + return x.PageInfo + } + return nil +} + +type Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` + OperationName string `protobuf:"bytes,2,opt,name=operation_name,json=operationName,proto3" json:"operation_name,omitempty"` + Variables *structpb.Struct `protobuf:"bytes,3,opt,name=variables,proto3" json:"variables,omitempty"` +} + +func (x *Request) Reset() { + *x = Request{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_graphql_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Request) ProtoMessage() {} + +func (x *Request) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_graphql_proto_msgTypes[6] + 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 Request.ProtoReflect.Descriptor instead. +func (*Request) Descriptor() ([]byte, []int) { + return file_larking_api_graphql_proto_rawDescGZIP(), []int{6} +} + +func (x *Request) GetQuery() string { + if x != nil { + return x.Query + } + return "" +} + +func (x *Request) GetOperationName() string { + if x != nil { + return x.OperationName + } + return "" +} + +func (x *Request) GetVariables() *structpb.Struct { + if x != nil { + return x.Variables + } + return nil +} + +type Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Data *structpb.Struct `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` + Errors []*Error `protobuf:"bytes,2,rep,name=errors,proto3" json:"errors,omitempty"` +} + +func (x *Response) Reset() { + *x = Response{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_graphql_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Response) ProtoMessage() {} + +func (x *Response) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_graphql_proto_msgTypes[7] + 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 Response.ProtoReflect.Descriptor instead. +func (*Response) Descriptor() ([]byte, []int) { + return file_larking_api_graphql_proto_rawDescGZIP(), []int{7} +} + +func (x *Response) GetData() *structpb.Struct { + if x != nil { + return x.Data + } + return nil +} + +func (x *Response) GetErrors() []*Error { + if x != nil { + return x.Errors + } + return nil +} + +type SourceLocation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Line int32 `protobuf:"varint,1,opt,name=line,proto3" json:"line,omitempty"` + Column int32 `protobuf:"varint,2,opt,name=column,proto3" json:"column,omitempty"` +} + +func (x *SourceLocation) Reset() { + *x = SourceLocation{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_graphql_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SourceLocation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SourceLocation) ProtoMessage() {} + +func (x *SourceLocation) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_graphql_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 SourceLocation.ProtoReflect.Descriptor instead. +func (*SourceLocation) Descriptor() ([]byte, []int) { + return file_larking_api_graphql_proto_rawDescGZIP(), []int{8} +} + +func (x *SourceLocation) GetLine() int32 { + if x != nil { + return x.Line + } + return 0 +} + +func (x *SourceLocation) GetColumn() int32 { + if x != nil { + return x.Column + } + return 0 +} + +type Error struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Locations []*SourceLocation `protobuf:"bytes,2,rep,name=locations,proto3" json:"locations,omitempty"` + Path []string `protobuf:"bytes,3,rep,name=path,proto3" json:"path,omitempty"` +} + +func (x *Error) Reset() { + *x = Error{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_graphql_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Error) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Error) ProtoMessage() {} + +func (x *Error) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_graphql_proto_msgTypes[9] + 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 Error.ProtoReflect.Descriptor instead. +func (*Error) Descriptor() ([]byte, []int) { + return file_larking_api_graphql_proto_rawDescGZIP(), []int{9} +} + +func (x *Error) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *Error) GetLocations() []*SourceLocation { + if x != nil { + return x.Locations + } + return nil +} + +func (x *Error) GetPath() []string { + if x != nil { + return x.Path + } + return nil +} + +var file_larking_api_graphql_proto_extTypes = []protoimpl.ExtensionInfo{ + { + ExtendedType: (*descriptorpb.MethodOptions)(nil), + ExtensionType: (*Rule)(nil), + Field: 72222228, + Name: "larking.api.graphql", + Tag: "bytes,72222228,opt,name=graphql", + Filename: "larking/api/graphql.proto", + }, + { + ExtendedType: (*descriptorpb.FieldOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 70000, + Name: "larking.api.relay_id", + Tag: "varint,70000,opt,name=relay_id", + Filename: "larking/api/graphql.proto", + }, + { + ExtendedType: (*descriptorpb.MessageOptions)(nil), + ExtensionType: (*Edge)(nil), + Field: 70001, + Name: "larking.api.edge", + Tag: "bytes,70001,opt,name=edge", + Filename: "larking/api/graphql.proto", + }, + { + ExtendedType: (*descriptorpb.MessageOptions)(nil), + ExtensionType: (*MessageConnection)(nil), + Field: 70002, + Name: "larking.api.connection", + Tag: "bytes,70002,opt,name=connection", + Filename: "larking/api/graphql.proto", + }, +} + +// Extension fields to descriptorpb.MethodOptions. +var ( + // Adds a method to the GraphQL query root. + // + // optional larking.api.Rule graphql = 72222228; + E_Graphql = &file_larking_api_graphql_proto_extTypes[0] +) + +// Extension fields to descriptorpb.FieldOptions. +var ( + // Adds relay + // + // optional bool relay_id = 70000; + E_RelayId = &file_larking_api_graphql_proto_extTypes[1] +) + +// Extension fields to descriptorpb.MessageOptions. +var ( + // optional larking.api.Edge edge = 70001; + E_Edge = &file_larking_api_graphql_proto_extTypes[2] + // optional larking.api.MessageConnection connection = 70002; + E_Connection = &file_larking_api_graphql_proto_extTypes[3] +) + +var File_larking_api_graphql_proto protoreflect.FileDescriptor + +var file_larking_api_graphql_proto_rawDesc = []byte{ + 0x0a, 0x19, 0x6c, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x71, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x6c, 0x61, 0x72, + 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 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, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0xf0, 0x01, 0x0a, 0x04, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x05, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x71, 0x75, 0x65, + 0x72, 0x79, 0x12, 0x1c, 0x0a, 0x08, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x24, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6c, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x41, 0x72, 0x67, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x17, 0x0a, 0x07, + 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, + 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x13, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x61, 0x6c, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6c, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x12, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x74, + 0x74, 0x65, 0x72, 0x6e, 0x22, 0x32, 0x0a, 0x04, 0x45, 0x64, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x22, 0x2f, 0x0a, 0x03, 0x41, 0x72, 0x67, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x65, 0x0a, 0x11, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x24, 0x0a, 0x04, 0x61, 0x72, + 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6c, 0x61, 0x72, 0x6b, 0x69, + 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x72, 0x67, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, + 0x22, 0x9c, 0x01, 0x0a, 0x08, 0x50, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x0a, + 0x0d, 0x68, 0x61, 0x73, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x68, 0x61, 0x73, 0x4e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, + 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x68, 0x61, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, + 0x73, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x68, 0x61, + 0x73, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x50, 0x61, 0x67, 0x65, 0x12, 0x21, 0x0a, + 0x0c, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, + 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6e, 0x64, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x22, + 0x6c, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, + 0x05, 0x65, 0x64, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, + 0x6e, 0x79, 0x52, 0x05, 0x65, 0x64, 0x67, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x09, 0x70, 0x61, 0x67, + 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, + 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x7d, 0x0a, + 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x25, + 0x0a, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x09, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, + 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, + 0x74, 0x52, 0x09, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x22, 0x63, 0x0a, 0x08, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, + 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2a, 0x0a, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6c, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x73, 0x22, 0x3c, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, + 0x70, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x39, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6c, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, + 0x68, 0x32, 0x5d, 0x0a, 0x07, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x12, 0x52, 0x0a, 0x05, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x14, 0x2e, 0x6c, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x6c, 0x61, + 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x5a, 0x0a, 0x12, 0x08, 0x2f, 0x67, + 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x22, 0x08, 0x2f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, + 0x3a, 0x4e, 0x0a, 0x07, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x12, 0x1e, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x94, 0x8c, 0xb8, 0x22, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6c, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x07, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, + 0x3a, 0x3d, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x69, 0x64, 0x12, 0x1d, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xf0, 0xa2, 0x04, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x49, 0x64, 0x88, 0x01, 0x01, 0x3a, + 0x48, 0x0a, 0x04, 0x65, 0x64, 0x67, 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xf1, 0xa2, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x6c, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, + 0x64, 0x67, 0x65, 0x52, 0x04, 0x65, 0x64, 0x67, 0x65, 0x3a, 0x61, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xf2, 0xa2, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1e, 0x2e, 0x6c, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x24, 0x5a, 0x22, + 0x6c, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, + 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x70, 0x62, 0x3b, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, + 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_larking_api_graphql_proto_rawDescOnce sync.Once + file_larking_api_graphql_proto_rawDescData = file_larking_api_graphql_proto_rawDesc +) + +func file_larking_api_graphql_proto_rawDescGZIP() []byte { + file_larking_api_graphql_proto_rawDescOnce.Do(func() { + file_larking_api_graphql_proto_rawDescData = protoimpl.X.CompressGZIP(file_larking_api_graphql_proto_rawDescData) + }) + return file_larking_api_graphql_proto_rawDescData +} + +var file_larking_api_graphql_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_larking_api_graphql_proto_goTypes = []interface{}{ + (*Rule)(nil), // 0: larking.api.Rule + (*Edge)(nil), // 1: larking.api.Edge + (*Arg)(nil), // 2: larking.api.Arg + (*MessageConnection)(nil), // 3: larking.api.MessageConnection + (*PageInfo)(nil), // 4: larking.api.PageInfo + (*Connection)(nil), // 5: larking.api.Connection + (*Request)(nil), // 6: larking.api.Request + (*Response)(nil), // 7: larking.api.Response + (*SourceLocation)(nil), // 8: larking.api.SourceLocation + (*Error)(nil), // 9: larking.api.Error + (*anypb.Any)(nil), // 10: google.protobuf.Any + (*structpb.Struct)(nil), // 11: google.protobuf.Struct + (*descriptorpb.MethodOptions)(nil), // 12: google.protobuf.MethodOptions + (*descriptorpb.FieldOptions)(nil), // 13: google.protobuf.FieldOptions + (*descriptorpb.MessageOptions)(nil), // 14: google.protobuf.MessageOptions +} +var file_larking_api_graphql_proto_depIdxs = []int32{ + 2, // 0: larking.api.Rule.args:type_name -> larking.api.Arg + 0, // 1: larking.api.Rule.additional_bindings:type_name -> larking.api.Rule + 2, // 2: larking.api.MessageConnection.args:type_name -> larking.api.Arg + 10, // 3: larking.api.Connection.edges:type_name -> google.protobuf.Any + 4, // 4: larking.api.Connection.page_info:type_name -> larking.api.PageInfo + 11, // 5: larking.api.Request.variables:type_name -> google.protobuf.Struct + 11, // 6: larking.api.Response.data:type_name -> google.protobuf.Struct + 9, // 7: larking.api.Response.errors:type_name -> larking.api.Error + 8, // 8: larking.api.Error.locations:type_name -> larking.api.SourceLocation + 12, // 9: larking.api.graphql:extendee -> google.protobuf.MethodOptions + 13, // 10: larking.api.relay_id:extendee -> google.protobuf.FieldOptions + 14, // 11: larking.api.edge:extendee -> google.protobuf.MessageOptions + 14, // 12: larking.api.connection:extendee -> google.protobuf.MessageOptions + 0, // 13: larking.api.graphql:type_name -> larking.api.Rule + 1, // 14: larking.api.edge:type_name -> larking.api.Edge + 3, // 15: larking.api.connection:type_name -> larking.api.MessageConnection + 6, // 16: larking.api.GraphQL.Query:input_type -> larking.api.Request + 7, // 17: larking.api.GraphQL.Query:output_type -> larking.api.Response + 17, // [17:18] is the sub-list for method output_type + 16, // [16:17] is the sub-list for method input_type + 13, // [13:16] is the sub-list for extension type_name + 9, // [9:13] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name +} + +func init() { file_larking_api_graphql_proto_init() } +func file_larking_api_graphql_proto_init() { + if File_larking_api_graphql_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_larking_api_graphql_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Rule); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_larking_api_graphql_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Edge); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_larking_api_graphql_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Arg); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_larking_api_graphql_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MessageConnection); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_larking_api_graphql_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PageInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_larking_api_graphql_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Connection); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_larking_api_graphql_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_larking_api_graphql_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_larking_api_graphql_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SourceLocation); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_larking_api_graphql_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Error); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_larking_api_graphql_proto_msgTypes[0].OneofWrappers = []interface{}{ + (*Rule_Query)(nil), + (*Rule_Mutation)(nil), + (*Rule_Subscription)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_larking_api_graphql_proto_rawDesc, + NumEnums: 0, + NumMessages: 10, + NumExtensions: 4, + NumServices: 1, + }, + GoTypes: file_larking_api_graphql_proto_goTypes, + DependencyIndexes: file_larking_api_graphql_proto_depIdxs, + MessageInfos: file_larking_api_graphql_proto_msgTypes, + ExtensionInfos: file_larking_api_graphql_proto_extTypes, + }.Build() + File_larking_api_graphql_proto = out.File + file_larking_api_graphql_proto_rawDesc = nil + file_larking_api_graphql_proto_goTypes = nil + file_larking_api_graphql_proto_depIdxs = nil +} diff --git a/api/graphqlpb/graphql_grpc.pb.go b/api/graphqlpb/graphql_grpc.pb.go new file mode 100644 index 0000000..bb761ee --- /dev/null +++ b/api/graphqlpb/graphql_grpc.pb.go @@ -0,0 +1,113 @@ +// Copyright 2021 Edward McFarlane. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v3.21.12 +// source: larking/api/graphql.proto + +package graphqlpb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + GraphQL_Query_FullMethodName = "/larking.api.GraphQL/Query" +) + +// GraphQLClient is the client API for GraphQL service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type GraphQLClient interface { + Query(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) +} + +type graphQLClient struct { + cc grpc.ClientConnInterface +} + +func NewGraphQLClient(cc grpc.ClientConnInterface) GraphQLClient { + return &graphQLClient{cc} +} + +func (c *graphQLClient) Query(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) { + out := new(Response) + err := c.cc.Invoke(ctx, GraphQL_Query_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GraphQLServer is the server API for GraphQL service. +// All implementations must embed UnimplementedGraphQLServer +// for forward compatibility +type GraphQLServer interface { + Query(context.Context, *Request) (*Response, error) + mustEmbedUnimplementedGraphQLServer() +} + +// UnimplementedGraphQLServer must be embedded to have forward compatible implementations. +type UnimplementedGraphQLServer struct { +} + +func (UnimplementedGraphQLServer) Query(context.Context, *Request) (*Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method Query not implemented") +} +func (UnimplementedGraphQLServer) mustEmbedUnimplementedGraphQLServer() {} + +// UnsafeGraphQLServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GraphQLServer will +// result in compilation errors. +type UnsafeGraphQLServer interface { + mustEmbedUnimplementedGraphQLServer() +} + +func RegisterGraphQLServer(s grpc.ServiceRegistrar, srv GraphQLServer) { + s.RegisterService(&GraphQL_ServiceDesc, srv) +} + +func _GraphQL_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GraphQLServer).Query(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: GraphQL_Query_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GraphQLServer).Query(ctx, req.(*Request)) + } + return interceptor(ctx, in, info, handler) +} + +// GraphQL_ServiceDesc is the grpc.ServiceDesc for GraphQL service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var GraphQL_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "larking.api.GraphQL", + HandlerType: (*GraphQLServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Query", + Handler: _GraphQL_Query_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "larking/api/graphql.proto", +} diff --git a/api/starwars.proto b/api/starwars.proto new file mode 100644 index 0000000..65d1c0c --- /dev/null +++ b/api/starwars.proto @@ -0,0 +1,111 @@ +// Copyright 2023 Edward McFarlane. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +syntax = "proto3"; + +package larking.api; + +import "google/api/annotations.proto"; +import "larking/api/graphql.proto"; +// import "google/protobuf/empty.proto"; + +option go_package = "larking.io/api/starwarspb;starwarspb"; + +message Faction { + // option (larking.api.relay).node = { + // rpc : "larking.testpb.StarWars.GetFaction(id : id)" + // method : "/larking.testpb.Starwars/GetFaction/" + // args : { + // "name" : "{id}" + // } + // id : "factions/{name}" + // match : "factions/*" + //}; + + string name = 1; + //[ (larking.api.relay).node = { + // method : "/larking.testpb.StarWars/GetFaction/" + // matches : "{name=factions/*}" + //} ]; + string display_name = 2; + + // arg "{parent}" + // arg "page_size:{first} + // query_arg { name : "after" field_path: " + + option (larking.api.edge) = { + name : "ships" + method : "/larking.api.StarWars/ListShips" + }; +} + +message GetFactionRequest { string name = 1; } + +message Ship { + // option (larking.api.relay).node = { + // rpc : "larking.testpb.StarWars.GetShip(id : id)" + //}; + + string name = 1; //[ (larking.api.relay_id) = true ]; + string display_name = 2; +} + +message GetShipRequest { string name = 1; } + +message ListShipsRequest { + string parent = 1; + int32 page_size = 2; + string page_token = 3; +} + +message ListShipsResponse { + repeated Ship ships = 1; + string next_page_token = 2; +} + +// type Query { +// rebels: Faction +// empire: Faction +// node(id: ID!): Node +//} +// +// type Mutation { +// introduceShip(input: IntroduceShipInput!): IntroduceShipPayload +//} +service StarWars { + + rpc GetFaction(GetFactionRequest) returns (Faction) { + option (larking.api.graphql) = { + query : "faction" + args {name : "id" field : "name"} + node_id : "{name=factions/*}" + + // TODO: empire/rebel routes? + // TODO: default constant args? + // additional_bindings { + // query : "rebels" + // args {"name" : "id=factions/1"} + //} + // additional_bindings { + // query : "empire" + // args {"name" : "id=factions/2"} + //} + }; + option (google.api.http) = { + get : "/v1/{name=factions/*}" + }; + } + + rpc ListShips(ListShipsRequest) returns (ListShipsResponse) { + option (google.api.http) = { + get : "/v1/{parent=factions/*}/ships" + }; + } + + rpc GetShip(GetShipRequest) returns (Ship) { + option (google.api.http) = { + get : "/v1/{name=factions/*/ships/*}" + }; + } +} diff --git a/api/starwarspb/starwars.pb.go b/api/starwarspb/starwars.pb.go new file mode 100644 index 0000000..06c2ca0 --- /dev/null +++ b/api/starwarspb/starwars.pb.go @@ -0,0 +1,555 @@ +// Copyright 2023 Edward McFarlane. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc v3.21.12 +// source: larking/api/starwars.proto + +package starwarspb + +import ( + _ "google.golang.org/genproto/googleapis/api/annotations" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + _ "larking.io/api/graphqlpb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Faction struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // [ (larking.api.relay).node = { + // method : "/larking.testpb.StarWars/GetFaction/" + // matches : "{name=factions/*}" + // } ]; + DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` +} + +func (x *Faction) Reset() { + *x = Faction{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_starwars_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Faction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Faction) ProtoMessage() {} + +func (x *Faction) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_starwars_proto_msgTypes[0] + 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 Faction.ProtoReflect.Descriptor instead. +func (*Faction) Descriptor() ([]byte, []int) { + return file_larking_api_starwars_proto_rawDescGZIP(), []int{0} +} + +func (x *Faction) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Faction) GetDisplayName() string { + if x != nil { + return x.DisplayName + } + return "" +} + +type GetFactionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *GetFactionRequest) Reset() { + *x = GetFactionRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_starwars_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetFactionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFactionRequest) ProtoMessage() {} + +func (x *GetFactionRequest) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_starwars_proto_msgTypes[1] + 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 GetFactionRequest.ProtoReflect.Descriptor instead. +func (*GetFactionRequest) Descriptor() ([]byte, []int) { + return file_larking_api_starwars_proto_rawDescGZIP(), []int{1} +} + +func (x *GetFactionRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type Ship struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` //[ (larking.api.relay_id) = true ]; + DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` +} + +func (x *Ship) Reset() { + *x = Ship{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_starwars_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Ship) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Ship) ProtoMessage() {} + +func (x *Ship) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_starwars_proto_msgTypes[2] + 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 Ship.ProtoReflect.Descriptor instead. +func (*Ship) Descriptor() ([]byte, []int) { + return file_larking_api_starwars_proto_rawDescGZIP(), []int{2} +} + +func (x *Ship) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Ship) GetDisplayName() string { + if x != nil { + return x.DisplayName + } + return "" +} + +type GetShipRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *GetShipRequest) Reset() { + *x = GetShipRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_starwars_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetShipRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetShipRequest) ProtoMessage() {} + +func (x *GetShipRequest) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_starwars_proto_msgTypes[3] + 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 GetShipRequest.ProtoReflect.Descriptor instead. +func (*GetShipRequest) Descriptor() ([]byte, []int) { + return file_larking_api_starwars_proto_rawDescGZIP(), []int{3} +} + +func (x *GetShipRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type ListShipsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"` + PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` +} + +func (x *ListShipsRequest) Reset() { + *x = ListShipsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_starwars_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListShipsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListShipsRequest) ProtoMessage() {} + +func (x *ListShipsRequest) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_starwars_proto_msgTypes[4] + 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 ListShipsRequest.ProtoReflect.Descriptor instead. +func (*ListShipsRequest) Descriptor() ([]byte, []int) { + return file_larking_api_starwars_proto_rawDescGZIP(), []int{4} +} + +func (x *ListShipsRequest) GetParent() string { + if x != nil { + return x.Parent + } + return "" +} + +func (x *ListShipsRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +func (x *ListShipsRequest) GetPageToken() string { + if x != nil { + return x.PageToken + } + return "" +} + +type ListShipsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ships []*Ship `protobuf:"bytes,1,rep,name=ships,proto3" json:"ships,omitempty"` + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` +} + +func (x *ListShipsResponse) Reset() { + *x = ListShipsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_larking_api_starwars_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListShipsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListShipsResponse) ProtoMessage() {} + +func (x *ListShipsResponse) ProtoReflect() protoreflect.Message { + mi := &file_larking_api_starwars_proto_msgTypes[5] + 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 ListShipsResponse.ProtoReflect.Descriptor instead. +func (*ListShipsResponse) Descriptor() ([]byte, []int) { + return file_larking_api_starwars_proto_rawDescGZIP(), []int{5} +} + +func (x *ListShipsResponse) GetShips() []*Ship { + if x != nil { + return x.Ships + } + return nil +} + +func (x *ListShipsResponse) GetNextPageToken() string { + if x != nil { + return x.NextPageToken + } + return "" +} + +var File_larking_api_starwars_proto protoreflect.FileDescriptor + +var file_larking_api_starwars_proto_rawDesc = []byte{ + 0x0a, 0x1a, 0x6c, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x74, + 0x61, 0x72, 0x77, 0x61, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x6c, 0x61, + 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x6c, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x22, 0x6e, 0x0a, 0x07, 0x46, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, + 0x4e, 0x61, 0x6d, 0x65, 0x3a, 0x2c, 0x8a, 0x97, 0x22, 0x28, 0x0a, 0x05, 0x73, 0x68, 0x69, 0x70, + 0x73, 0x12, 0x1f, 0x2f, 0x6c, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x53, 0x74, 0x61, 0x72, 0x57, 0x61, 0x72, 0x73, 0x2f, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x69, + 0x70, 0x73, 0x22, 0x27, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x46, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3d, 0x0a, 0x04, 0x53, + 0x68, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, + 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, + 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x24, 0x0a, 0x0e, 0x47, 0x65, + 0x74, 0x53, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x22, 0x66, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x69, 0x70, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, + 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, + 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, + 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x64, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, + 0x53, 0x68, 0x69, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, + 0x05, 0x73, 0x68, 0x69, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6c, + 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x68, 0x69, 0x70, 0x52, + 0x05, 0x73, 0x68, 0x69, 0x70, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, + 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x32, 0xf1, + 0x02, 0x0a, 0x08, 0x53, 0x74, 0x61, 0x72, 0x57, 0x61, 0x72, 0x73, 0x12, 0x8f, 0x01, 0x0a, 0x0a, + 0x47, 0x65, 0x74, 0x46, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x6c, 0x61, 0x72, + 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x6c, 0x61, 0x72, + 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x46, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x4b, 0xa2, 0xe1, 0xc0, 0x93, 0x02, 0x28, 0x22, 0x0a, 0x0a, 0x02, 0x69, 0x64, 0x12, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x2a, 0x11, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x66, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x0a, 0x07, 0x66, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, + 0x65, 0x3d, 0x66, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x12, 0x71, 0x0a, + 0x09, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x69, 0x70, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x61, 0x72, + 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x69, + 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x61, 0x72, 0x6b, + 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x69, 0x70, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1f, 0x12, 0x1d, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x66, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x73, 0x68, 0x69, 0x70, 0x73, + 0x12, 0x60, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x53, 0x68, 0x69, 0x70, 0x12, 0x1b, 0x2e, 0x6c, 0x61, + 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x69, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x6c, 0x61, 0x72, 0x6b, 0x69, + 0x6e, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x68, 0x69, 0x70, 0x22, 0x25, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x66, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x68, 0x69, 0x70, 0x73, 0x2f, + 0x2a, 0x7d, 0x42, 0x26, 0x5a, 0x24, 0x6c, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x69, 0x6f, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x72, 0x77, 0x61, 0x72, 0x73, 0x70, 0x62, 0x3b, + 0x73, 0x74, 0x61, 0x72, 0x77, 0x61, 0x72, 0x73, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_larking_api_starwars_proto_rawDescOnce sync.Once + file_larking_api_starwars_proto_rawDescData = file_larking_api_starwars_proto_rawDesc +) + +func file_larking_api_starwars_proto_rawDescGZIP() []byte { + file_larking_api_starwars_proto_rawDescOnce.Do(func() { + file_larking_api_starwars_proto_rawDescData = protoimpl.X.CompressGZIP(file_larking_api_starwars_proto_rawDescData) + }) + return file_larking_api_starwars_proto_rawDescData +} + +var file_larking_api_starwars_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_larking_api_starwars_proto_goTypes = []interface{}{ + (*Faction)(nil), // 0: larking.api.Faction + (*GetFactionRequest)(nil), // 1: larking.api.GetFactionRequest + (*Ship)(nil), // 2: larking.api.Ship + (*GetShipRequest)(nil), // 3: larking.api.GetShipRequest + (*ListShipsRequest)(nil), // 4: larking.api.ListShipsRequest + (*ListShipsResponse)(nil), // 5: larking.api.ListShipsResponse +} +var file_larking_api_starwars_proto_depIdxs = []int32{ + 2, // 0: larking.api.ListShipsResponse.ships:type_name -> larking.api.Ship + 1, // 1: larking.api.StarWars.GetFaction:input_type -> larking.api.GetFactionRequest + 4, // 2: larking.api.StarWars.ListShips:input_type -> larking.api.ListShipsRequest + 3, // 3: larking.api.StarWars.GetShip:input_type -> larking.api.GetShipRequest + 0, // 4: larking.api.StarWars.GetFaction:output_type -> larking.api.Faction + 5, // 5: larking.api.StarWars.ListShips:output_type -> larking.api.ListShipsResponse + 2, // 6: larking.api.StarWars.GetShip:output_type -> larking.api.Ship + 4, // [4:7] is the sub-list for method output_type + 1, // [1:4] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_larking_api_starwars_proto_init() } +func file_larking_api_starwars_proto_init() { + if File_larking_api_starwars_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_larking_api_starwars_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Faction); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_larking_api_starwars_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetFactionRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_larking_api_starwars_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Ship); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_larking_api_starwars_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetShipRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_larking_api_starwars_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListShipsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_larking_api_starwars_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListShipsResponse); 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{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_larking_api_starwars_proto_rawDesc, + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_larking_api_starwars_proto_goTypes, + DependencyIndexes: file_larking_api_starwars_proto_depIdxs, + MessageInfos: file_larking_api_starwars_proto_msgTypes, + }.Build() + File_larking_api_starwars_proto = out.File + file_larking_api_starwars_proto_rawDesc = nil + file_larking_api_starwars_proto_goTypes = nil + file_larking_api_starwars_proto_depIdxs = nil +} diff --git a/api/starwarspb/starwars_grpc.pb.go b/api/starwarspb/starwars_grpc.pb.go new file mode 100644 index 0000000..896a31f --- /dev/null +++ b/api/starwarspb/starwars_grpc.pb.go @@ -0,0 +1,187 @@ +// Copyright 2023 Edward McFarlane. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v3.21.12 +// source: larking/api/starwars.proto + +package starwarspb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + StarWars_GetFaction_FullMethodName = "/larking.api.StarWars/GetFaction" + StarWars_ListShips_FullMethodName = "/larking.api.StarWars/ListShips" + StarWars_GetShip_FullMethodName = "/larking.api.StarWars/GetShip" +) + +// StarWarsClient is the client API for StarWars service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type StarWarsClient interface { + GetFaction(ctx context.Context, in *GetFactionRequest, opts ...grpc.CallOption) (*Faction, error) + ListShips(ctx context.Context, in *ListShipsRequest, opts ...grpc.CallOption) (*ListShipsResponse, error) + GetShip(ctx context.Context, in *GetShipRequest, opts ...grpc.CallOption) (*Ship, error) +} + +type starWarsClient struct { + cc grpc.ClientConnInterface +} + +func NewStarWarsClient(cc grpc.ClientConnInterface) StarWarsClient { + return &starWarsClient{cc} +} + +func (c *starWarsClient) GetFaction(ctx context.Context, in *GetFactionRequest, opts ...grpc.CallOption) (*Faction, error) { + out := new(Faction) + err := c.cc.Invoke(ctx, StarWars_GetFaction_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *starWarsClient) ListShips(ctx context.Context, in *ListShipsRequest, opts ...grpc.CallOption) (*ListShipsResponse, error) { + out := new(ListShipsResponse) + err := c.cc.Invoke(ctx, StarWars_ListShips_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *starWarsClient) GetShip(ctx context.Context, in *GetShipRequest, opts ...grpc.CallOption) (*Ship, error) { + out := new(Ship) + err := c.cc.Invoke(ctx, StarWars_GetShip_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// StarWarsServer is the server API for StarWars service. +// All implementations must embed UnimplementedStarWarsServer +// for forward compatibility +type StarWarsServer interface { + GetFaction(context.Context, *GetFactionRequest) (*Faction, error) + ListShips(context.Context, *ListShipsRequest) (*ListShipsResponse, error) + GetShip(context.Context, *GetShipRequest) (*Ship, error) + mustEmbedUnimplementedStarWarsServer() +} + +// UnimplementedStarWarsServer must be embedded to have forward compatible implementations. +type UnimplementedStarWarsServer struct { +} + +func (UnimplementedStarWarsServer) GetFaction(context.Context, *GetFactionRequest) (*Faction, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetFaction not implemented") +} +func (UnimplementedStarWarsServer) ListShips(context.Context, *ListShipsRequest) (*ListShipsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListShips not implemented") +} +func (UnimplementedStarWarsServer) GetShip(context.Context, *GetShipRequest) (*Ship, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetShip not implemented") +} +func (UnimplementedStarWarsServer) mustEmbedUnimplementedStarWarsServer() {} + +// UnsafeStarWarsServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to StarWarsServer will +// result in compilation errors. +type UnsafeStarWarsServer interface { + mustEmbedUnimplementedStarWarsServer() +} + +func RegisterStarWarsServer(s grpc.ServiceRegistrar, srv StarWarsServer) { + s.RegisterService(&StarWars_ServiceDesc, srv) +} + +func _StarWars_GetFaction_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetFactionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StarWarsServer).GetFaction(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StarWars_GetFaction_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StarWarsServer).GetFaction(ctx, req.(*GetFactionRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StarWars_ListShips_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListShipsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StarWarsServer).ListShips(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StarWars_ListShips_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StarWarsServer).ListShips(ctx, req.(*ListShipsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StarWars_GetShip_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetShipRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StarWarsServer).GetShip(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: StarWars_GetShip_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StarWarsServer).GetShip(ctx, req.(*GetShipRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// StarWars_ServiceDesc is the grpc.ServiceDesc for StarWars service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var StarWars_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "larking.api.StarWars", + HandlerType: (*StarWarsServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetFaction", + Handler: _StarWars_GetFaction_Handler, + }, + { + MethodName: "ListShips", + Handler: _StarWars_ListShips_Handler, + }, + { + MethodName: "GetShip", + Handler: _StarWars_GetShip_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "larking/api/starwars.proto", +} diff --git a/go.mod b/go.mod index b83b498..063b6b3 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/pool v0.2.1 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/graphql-go/graphql v0.8.1 // indirect golang.org/x/sys v0.7.0 // indirect golang.org/x/text v0.9.0 // indirect ) diff --git a/go.sum b/go.sum index a7501e7..5f99bde 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/graphql-go/graphql v0.8.1 h1:p7/Ou/WpmulocJeEx7wjQy611rtXGQaAcXGqanuMMgc= +github.com/graphql-go/graphql v0.8.1/go.mod h1:nKiHzRM0qopJEwCITUuIsxk9PlVlwIiiI8pnJEhordQ= golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= @@ -26,7 +28,5 @@ google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.1-0.20230501154320-cf06b0c33cda h1:CGKs/jtLmFiQ0tmmt8ykIoaKqn+yi8T/reVFvwOR5aY= google.golang.org/protobuf v1.30.1-0.20230501154320-cf06b0c33cda/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= diff --git a/larking/graphql.go b/larking/graphql.go new file mode 100644 index 0000000..175fae4 --- /dev/null +++ b/larking/graphql.go @@ -0,0 +1,271 @@ +package larking + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/graphql-go/graphql" + "github.com/graphql-go/graphql/gqlerrors" + "github.com/graphql-go/graphql/language/location" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/known/structpb" + "larking.io/api/graphqlpb" +) + +// getExtensionGraphQL returns the graphql extension of the proto message. +func getExtensionGraphQL(m proto.Message) *graphqlpb.Rule { + return proto.GetExtension(m, graphqlpb.E_Graphql).(*graphqlpb.Rule) +} + +type stateKeyT struct{} + +var stateKey stateKeyT + +func ctxWithState(ctx context.Context, s *state) context.Context { + return context.WithValue(ctx, stateKey, s) +} +func stateFromCtx(ctx context.Context) *state { + return ctx.Value(stateKey).(*state) +} + +type streamCall struct { + ctx context.Context + name string + params params + send proto.Message +} + +func (s *streamCall) SetHeader(md metadata.MD) error { return nil } +func (s *streamCall) SendHeader(md metadata.MD) error { return nil } +func (s *streamCall) SetTrailer(md metadata.MD) {} + +func (s *streamCall) Context() context.Context { + sts := &serverTransportStream{s, s.name} + return grpc.NewContextWithServerTransportStream(s.ctx, sts) +} + +func (s *streamCall) SendMsg(v any) error { + s.send = v.(proto.Message) + return nil +} + +func (s *streamCall) RecvMsg(m interface{}) error { + args := m.(proto.Message) + + if err := s.params.set(args); err != nil { + return err + } + return nil +} + +func parseGraphQLParam(fds []protoreflect.FieldDescriptor, val any) (param, error) { + if len(fds) == 0 { + return param{}, fmt.Errorf("zero field") + } + fd := fds[len(fds)-1] + + switch kind := fd.Kind(); kind { + case protoreflect.StringKind: + return param{fds: fds, val: protoreflect.ValueOfString(val.(string))}, nil + default: + return param{}, fmt.Errorf("unsupported kind %v", kind) + } +} + +func (s *state) addGraphQLRule( + opts muxOptions, + rule *graphqlpb.Rule, + desc protoreflect.MethodDescriptor, + name string, +) error { + fmt.Println("addGraphQLRule", rule) + fmt.Println("desc", desc) + + // TODO + + // Schema + + factionType := graphql.NewObject(graphql.ObjectConfig{ + Name: "Faction", + Description: "Faction type", + Fields: graphql.Fields{ + "name": &graphql.Field{ + Type: graphql.NewNonNull(graphql.String), + Description: "The name of the faction.", + Resolve: func(p graphql.ResolveParams) (any, error) { + if msg, ok := p.Source.(proto.Message); ok { + mr := msg.ProtoReflect() + desc := mr.Descriptor() + fd := desc.Fields().ByJSONName("name") + return mr.Get(fd).Interface(), nil + } + return nil, nil + }, + }, + "displayName": &graphql.Field{ + Type: graphql.String, + Description: "The displayName of the faction.", + Resolve: func(p graphql.ResolveParams) (any, error) { + if msg, ok := p.Source.(proto.Message); ok { + mr := msg.ProtoReflect() + desc := mr.Descriptor() + fd := desc.Fields().ByJSONName("displayName") + return mr.Get(fd).Interface(), nil + } + return nil, nil + }, + }, + }, + }) + + msgDesc := desc.Input() + fieldDescs := msgDesc.Fields() + + queryType := graphql.NewObject(graphql.ObjectConfig{ + Name: "Query", + Fields: graphql.Fields{ + "faction": &graphql.Field{ + Type: factionType, + Args: graphql.FieldConfigArgument{ + "name": &graphql.ArgumentConfig{ + Description: "faction description", + Type: graphql.String, + }, + }, + Resolve: func(p graphql.ResolveParams) (any, error) { + // fetch data from handler + // convert to structpb.pb + ctx := p.Context + s := stateFromCtx(ctx) + fmt.Println("state", s) + fmt.Println("p", p.Args) + + var params params + for k, v := range p.Args { + fd := fieldDescs.ByJSONName(k) + p, err := parseGraphQLParam([]protoreflect.FieldDescriptor{fd}, v) + if err != nil { + return nil, err + } + params = append(params, p) + } + + hd, err := s.pickMethodHandler(name) + if err != nil { + return nil, err + } + + stream := &streamCall{ + ctx: ctx, + name: name, + params: params, + } + if err := hd.handler(&opts, stream); err != nil { + return nil, err + } + fmt.Println("stream.send", stream.send) + return stream.send, nil + }, + }, + }, + }) + + schemaConfig := graphql.SchemaConfig{ + Query: queryType, + } + + var err error + s.gqlSchema, err = graphql.NewSchema(schemaConfig) + if err != nil { + return err + } + + return nil +} + +func toGraphQLPath(path []any) []string { + if len(path) == 0 { + return nil + } + r := make([]string, len(path)) + for i, p := range path { + r[i] = p.(string) + } + return r +} + +func toGraphQLLocations(locs []location.SourceLocation) []*graphqlpb.SourceLocation { + if len(locs) == 0 { + return nil + } + r := make([]*graphqlpb.SourceLocation, len(locs)) + for i, loc := range locs { + r[i] = &graphqlpb.SourceLocation{ + Line: int32(loc.Line), + Column: int32(loc.Column), + } + } + return r +} + +func toGraphQLErrors(errs []gqlerrors.FormattedError) []*graphqlpb.Error { + if len(errs) == 0 { + return nil + } + r := make([]*graphqlpb.Error, len(errs)) + for i, err := range errs { + r[i] = &graphqlpb.Error{ + Message: err.Message, + Locations: toGraphQLLocations(err.Locations), + Path: toGraphQLPath(err.Path), + } + } + return r +} + +// TODO: figure out how to keep structpb.Values +func toGraphQLData(data any) *structpb.Struct { + fmt.Println("toGraphqlData", data) + for k, v := range data.(map[string]interface{}) { + fmt.Println("k", k) + fmt.Println("v", v) + fmt.Printf("%T\n", v) + + //s.Fields[k] = &structpb.Value{ + // Kind: &structpb.Value_StringValue{ + // StringValue: v.(string), + // }, + //} + } + b, _ := json.Marshal(data) + var s structpb.Struct + protojson.Unmarshal(b, &s) + return &s +} + +func (m *Mux) Query(ctx context.Context, req *graphqlpb.Request) (*graphqlpb.Response, error) { + s := m.loadState() + if s == nil { + return nil, fmt.Errorf("schema not loaded") + } + ctx = ctxWithState(ctx, s) + + params := graphql.Params{ + Schema: s.gqlSchema, + RequestString: req.Query, + VariableValues: nil, // TODO: req.Variables.Fields, + OperationName: req.OperationName, + Context: ctx, + } + result := graphql.Do(params) + fmt.Println(result) + return &graphqlpb.Response{ + Data: toGraphQLData(result.Data), + Errors: toGraphQLErrors(result.Errors), + }, nil +} diff --git a/larking/graphql_test.go b/larking/graphql_test.go new file mode 100644 index 0000000..82e1da2 --- /dev/null +++ b/larking/graphql_test.go @@ -0,0 +1,204 @@ +package larking + +import ( + "context" + "errors" + "testing" + + "github.com/google/go-cmp/cmp" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/testing/protocmp" + "google.golang.org/protobuf/types/known/structpb" + "larking.io/api/graphqlpb" + "larking.io/api/starwarspb" +) + +type starWarsServer struct { + starwarspb.UnimplementedStarWarsServer + + factions map[string]*starwarspb.Faction + ships map[string]*starwarspb.Ship + factionShips map[string][]*starwarspb.Ship +} + +func newStarWarsServer(t *testing.T) *starWarsServer { + var ( + xwing = &starwarspb.Ship{ + Name: "factions/rebels/ships/1", + DisplayName: "X-Wing", + } + ywing = &starwarspb.Ship{ + Name: "factions/rebels/ships/2", + DisplayName: "Y-Wing", + } + awing = &starwarspb.Ship{ + Name: "factions/rebels/ships/3", + DisplayName: "A-Wing", + } + falcon = &starwarspb.Ship{ + Name: "factions/rebels/ships/4", + DisplayName: "Millenium Falcon", + } + homeOne = &starwarspb.Ship{ + Name: "factions/rebels/ships/5", + DisplayName: "Home One", + } + tieFighter = &starwarspb.Ship{ + Name: "factions/empire/ships/6", + DisplayName: "TIE Fighter", + } + tieInterceptor = &starwarspb.Ship{ + Name: "factions/empire/ships/7", + DisplayName: "TIE Interceptor", + } + executor = &starwarspb.Ship{ + Name: "factions/empire/ships/8", + DisplayName: "Executor", + } + + rebels = &starwarspb.Faction{ + Name: "factions/rebels", + DisplayName: "Alliance to Restore the Republic", + } + empire = &starwarspb.Faction{ + Name: "factions/empire", + DisplayName: "Galactic Empire", + } + ) + + return &starWarsServer{ + factions: map[string]*starwarspb.Faction{ + "factions/rebels": rebels, + "factions/empire": empire, + }, + ships: map[string]*starwarspb.Ship{ + "factions/rebels/ships/1": xwing, + "factions/rebels/ships/2": ywing, + "factions/rebels/ships/3": awing, + "factions/rebels/ships/4": falcon, + "factions/rebels/ships/5": homeOne, + "factions/empire/ships/6": tieFighter, + "factions/empire/ships/7": tieInterceptor, + "factions/empire/ships/8": executor, + }, + factionShips: map[string][]*starwarspb.Ship{ + "factions/1": {xwing, ywing, awing, falcon, homeOne}, + "factions/2": {tieFighter, tieInterceptor, executor}, + }, + } +} + +func (s *starWarsServer) GetFaction(ctx context.Context, req *starwarspb.GetFactionRequest) (*starwarspb.Faction, error) { + //id := strings.TrimPrefix("factions/", req.Name) + v, ok := s.factions[req.Name] + if !ok { + return nil, status.Errorf(codes.NotFound, "missing faction: %s", req.Name) + } + return v, nil +} + +func (s *starWarsServer) GetShip(ctx context.Context, req *starwarspb.GetShipRequest) (*starwarspb.Ship, error) { + //id := strings.TrimPrefix("ships/", req.Name) + v, ok := s.ships[req.Name] + if !ok { + return nil, status.Errorf(codes.NotFound, "missing ship: %s", req.Name) + } + return v, nil +} + +func (s *starWarsServer) ListShips(ctx context.Context, req *starwarspb.ListShipsRequest) (*starwarspb.ListShipsResponse, error) { + //pid := strings.TrimPrefix(req.Parent, "factions/") + vs, ok := s.factionShips[req.Parent] + if !ok { + return nil, status.Errorf(codes.NotFound, "missing factions ships: %s", req.Parent) + } + pageSize := int(req.PageSize) + if pageSize <= 0 { + pageSize = 10 + } + pageToken := req.PageToken + + if pageToken != "" { + for i, v := range vs { + if v.Name == pageToken { + vs = vs[i+1:] + break + } + } + } + + if len(vs) > pageSize { + vs = vs[:pageSize] + } + + var nextPageToken string + if len(vs) > 0 { + nextPageToken = vs[len(vs)-1].Name + } + + return &starwarspb.ListShipsResponse{ + Ships: vs, + NextPageToken: nextPageToken, + }, nil +} + +func TestGraphQL(t *testing.T) { + m, err := NewMux() + if err != nil { + t.Fatal(err) + } + svr := newStarWarsServer(t) + starwarspb.RegisterStarWarsServer(m, svr) + + toStruct := func(str string) *structpb.Struct { + var s structpb.Struct + if err := protojson.Unmarshal([]byte(str), &s); err != nil { + t.Fatal(err) + } + return &s + } + + //t.Skip("TODO") + tests := []struct { + name string + req *graphqlpb.Request + rsp *graphqlpb.Response + err error + }{{ + name: "hero", + req: &graphqlpb.Request{ + Query: `{ + faction(name: "factions/rebels") { + name + displayName + } + }`, + }, + rsp: &graphqlpb.Response{ + Data: toStruct(`{ + "faction": { + "name": "factions/rebels", + "displayName": "Alliance to Restore the Republic" + } + }`), + }, + }} + cmpOpts := cmp.Options{protocmp.Transform()} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + rsp, err := m.Query(ctx, tt.req) + if err != nil { + if errors.Is(err, tt.err) { + t.Skip(err) + } + t.Fatal(err) + } + if diff := cmp.Diff(tt.rsp, rsp, cmpOpts...); diff != "" { + t.Errorf("diff: %s", diff) + } + }) + } +} diff --git a/larking/mux.go b/larking/mux.go index 485cf2f..6c94585 100644 --- a/larking/mux.go +++ b/larking/mux.go @@ -21,6 +21,7 @@ import ( "time" "github.com/gobwas/ws" + "github.com/graphql-go/graphql" "google.golang.org/genproto/googleapis/api/annotations" "google.golang.org/genproto/googleapis/api/httpbody" "google.golang.org/genproto/googleapis/api/serviceconfig" @@ -46,9 +47,10 @@ type connList struct { } type state struct { - path *path - conns map[*grpc.ClientConn]connList - handlers map[string][]*handler + path *path + conns map[*grpc.ClientConn]connList + handlers map[string][]*handler + gqlSchema graphql.Schema } func (s *state) clone() *state { @@ -448,6 +450,14 @@ func (s *state) appendHandler( return fmt.Errorf("[%s] invalid rule %s: %w", desc.FullName(), rule.String(), err) } } + + // Add graphql rules. + if rule := getExtensionGraphQL(desc.Options()); rule != nil { + if err := s.addGraphQLRule(opts, rule, desc, h.method); err != nil { + return fmt.Errorf("[%s] invalid graphQL rule %s: %w", desc.FullName(), rule.String(), err) + } + } + s.handlers[h.method] = append(s.handlers[h.method], h) return nil }