Meetup GO BH - Jun, 2020
/rodrigo-brito
@RodrigoFBrito
RAID: Refactoring-aware and Intelligent Diffs
Layout by Zeno Rocha - Codepen
Dê ao seu cliente o poder de pedir exatamente o que ele precisa
https://api.example/v1/user/{ID}
Exemplo: api.example/v1/user/123
Parâmetros
Operação
{
id: 123,
name: "Fulano da Silva",
email: "fulano@fulano.com.br",
phone: "(31) 1234-4567",
city: "Belo Horizonte"
}
Exemplo: api.example/graphql
{
user(id: 123) {
name
}
}
Parâmetros
Operação
O usuário pode fazer várias consultas em uma requisição
{
name: "Fulano da Silva"
}
type Message {
author: String!
content: String!
}
type Query {
messages(limit: Int!): [Message!]
}
type Mutation {
sendMessage(input: MessageInput!): Message
}
Interface / Assinaturas da API
type Subscription {
newMessage(chat: ID!): Message
}
Mutation
Subscription
Topic
Exemplo: github.com/99designs/gqlgen
type Message {
author: string!
content: string!
}
query {
messages(limit: Int!): [Message!]
}
type Message struct {
Author string
Content string
}
type QueryRoot interface {
Messages(limit int) ([]*Message, error)
}
type Query struct { ... }
func (s Query) Messages(limit int) ([]*Message, error) {
// your logic here...
}
schema.graphql
Documentação: https://gqlgen.com/config/
schema:
- schema.graphql
exec:
filename: schema_gen.go
package: graphql
model:
filename: model/models_gen.go
package: model
.gqlgen.yaml
$ go get -u github.com/99designs/gqlgen
$ gqlgen generate
type Query struct {
MessageService service.Message
}
func (q Query) Messages(ctx context.Context, limit int) ([]*model.Message, error) {
return q.MessageService.Fetch(ctx, limit)
}
type QueryResolver interface {
Messages(ctx context.Context, limit int) ([]*model.Message, error)
}
Interface Requerida
Implementação
type Mutation struct {
MessageService service.Message
}
func (m Mutation) SendMessage(ctx context.Context, input model.MessageInput) (*model.Message, error) {
message := model.Message{
AuthorID: input.AuthorID,
Author: input.Author,
Content: input.Message,
CreatedAt: time.Now(),
}
err := m.MessageService.Save(ctx, message)
if err != nil {
return nil, ErrServiceUnavailable
}
return &message, nil
}
type MutationResolver interface {
SendMessage(ctx context.Context, input model.MessageInput) (*model.Message, error)
}
Interface Requerida
Implementação
func (s Subscription) Messages(ctx context.Context) (<-chan *model.Message, error) {
subscription := s.PubSub.Sub(topicName)
messages := make(chan *model.Message)
go func() {
for {
select {
case <-ctx.Done():
s.PubSub.Unsub(subscription, topicName)
case message := <-subscription:
if message != nil {
messages <- message.(*model.Message)
}
}
}
}()
return messages, nil
}
type SubscriptionResolver interface {
Messages(ctx context.Context) (<-chan *model.Message, error)
}
Interface Requerida
Implementação
const QUERY_MESSAGES = gql`
query Messages {
messages(limit: 100) {
authorID
author
content
}
}
`;
function Messages() {
const { loading, error, data } = useQuery<Query>(QUERY_MESSAGES);
return (
<div>
{data.messages.map((message, index) => (
<p key={index}>
{message.content}
</p>
))}
</div>
div
}
const MUTATION_SEND_MESSAGE = gql`
mutation($input: MessageInput!) {
sendMessage(input: $input) {
authorID
author
content
}
}
`;
const [sendMessage] = useMutation<Mutation, MutationSendMessageArgs>(
MUTATION_SEND_MESSAGE
);
const onSubmit = (e: FormEvent) => {
sendMessage({
variables: {
input: {
authorID: uuid,
author: name,
message: message,
},
},
});
}
const SUBSCRIPTION_MESSAGES = gql`
subscription {
messages {
authorID
author
content
}
}
`;
useSubscription<Subscription>(SUBSCRIPTION_MESSAGES, {
onSubscriptionData: (data) => {
const result = data.subscriptionData.data.messages;
setConversation([
...conversation, { author: result.author, content: result.content },
]);
},
});