USP de São Carlos ➔ Full Stack Developer na startup Easy Carros ➔ Hackathons ◆ 1º lugar - Hackathon Globo 2016 ◆ 1º lugar - MasterCard Code4Inclusion Miami ◆ 2º lugar - Masters of Code São Paulo ◆ 1º lugar - Destination Hack ◆ 1º lugar - API Hackday SP @brunolemos
4,5] } GET /v1/users/2/posts/last {_id: ‘post_2a’} GET /v1/users/3/posts/last {_id: ‘post_3a’} GET /v1/users/4/posts/last {_id: ‘post_4a’} GET /v1/users/5/posts/last {_id: ‘post_5a’} 1. Motivação Muitas requisições… Já sei, vou criar um endpoint para isso.
GET /v1/myFriendsLastPosts [{_id: 1, lastPost: {...}}, {_id: 2, lastPost: {...}}] Usando “REST” 1. Motivação // faço o merge dos resultados no client [{_id: 1, lastPost: {...}, pages: [...]}, ...] // já sei! que tal um novo endpoint? GET /v1/myFriendsLastPostsAndPages
dados serão retornados? #surprise Como descobrir: 1. Fazer uma requisição de teste 2. Ler a documentação (pode estar desatualizada) 3. Ler o código Dados retornados: 1. Provavelmente muito mais do que você precisa 1. Motivação
formato da entrada Entrada dos dados que precisa Camada do GraphQL Diferentes clients Bancos de dados Servidor Retorno da função “resolve” com os dados desejados
de onde quiser // Funções “resolve” são as responsáveis por dizer onde pegar os dados. // Podem retornar dados de qualquer lugar, desde que retorne o valor final ou uma Promise. // Exemplos para query { user(_id: “xxx”) { name } } resolve: (root, args, context) => ({ name: ‘Bruno Lemos’, outroCampo: ‘X’ }), // Dado arbitrário resolve: (root, args, context) => User.findById(args._id), // Método que retorna uma promise resolve: (root, args, context) => fetch(‘http://api.site.com/v1/user’), // API externa Características Funções “resolve”
{ _id name } user(_id: “xxx_2”) { github } } { "errors": [{ "message": "Fields \"user\" conflict because they have differing arguments. use different aliases on the fields to fetch both if this was intentional." }] }
} ... on User { name age } } } Query: Múltiplos tipos Sintaxe { "data": { "me": { "__typename": "Admin", "name": "Bruno Lemos" } } } A query ‘me’ pode retornar um tipo diferente dependendo de quem está logado no momento
} ... on User { name age } } } Query: Múltiplos tipos Sintaxe { "data": { "me": { "__typename": "User", "name": "Bruno Lemos", "age": 23 } } } A query ‘me’ pode retornar um tipo diferente dependendo de quem está logado no momento
{ type: new GraphQLNonNull(GraphQLID) }, name: { type: GraphQLString }, }, }); Precisamos criar o tipo Usuário, que será o retorno da query Tipos já existentes: ID, String, Int, Boolean, Object, Enum, List, … (ver lista completa) Criando o servidor
de retorno, os argumentos de entrada e a função “resolve” Criando o servidor // bluebird converte uma funcao que pussui callback em uma promise const getUserAsync = Bluebird.promisify(myMethodFromOldApiThatUsesCallback); export default { type: UserType, // arquivo criado anteriormente args: { _id: { type: new GraphQLNonNull(GraphQLID) }, }, resolve: (root, args, context) => getUserAsync(args._id), // onde a mágica acontece };
fields: { user: UserQuery, // arquivo criado anteriormente // users: ..., // aqui iria as outras queries // posts: ..., }, }), mutation: ..., // definirá todas as mutations existentes (mesma sintaxe acima) }); Schemas possuem uma RootQuery e uma RootMutation Criando o servidor