Crie um Servidor Express com GraphQL
Nota
Escrevi o artigo original em espanhol. Portanto, algumas referências a recursos e código estão em espanhol.
Pré-requisitos
Para executar e entender melhor os passos, é necessário ter:
nodejs
instalado (e portantonpm
também).
Criação do Projeto
Criar um servidor com Express e GraphQL é relativamente simples. Para começar, navegue até a pasta onde deseja criar o servidor. Abra o console dentro da pasta, crie um diretório e navegue para dentro dele. Neste caso, a pasta será chamada express-gql
.
$ mkdir express-gql
$ cd express-gql
Vamos inicializar o projeto com npm
usando npm init
. Preencha as opções solicitadas.
$ npm init
Em seguida, complete as opções. Se você não inserir nada, o valor padrão será selecionado automaticamente. Você pode substituir <author-name>
por seu nome.
Este utilitário irá guiá-lo na criação de um arquivo package.json.
Ele cobre apenas os itens mais comuns e tenta adivinhar padrões sensatos.
Consulte `npm help json` para documentação definitiva sobre esses campos
e exatamente o que eles fazem.
Use `npm install <pkg>` depois para instalar um pacote e
salvá-lo como uma dependência no arquivo package.json.
Pressione ^C a qualquer momento para sair.
nome do pacote: (express-gql)
versão: (1.0.0)
descrição: Um servidor com graphql
ponto de entrada: (index.js)
comando de teste:
repositório git:
palavras-chave:
autor: <author-name>
licença: (ISC) MIT
Sobre escrever em /<...caminho-para-pasta>/express-gql/package.json:
{
"name": "express-gql",
"version": "1.0.0",
"description": "Um servidor com graphql",
"main": "index.js",
"scripts": {
"test": "echo \"Erro: nenhum teste especificado\" && exit 1"
},
"author": "<author-name>",
"license": "MIT"
}
Isso está OK? (yes) yes
Após isso, instale as dependências necessárias com o seguinte comando:
$ npm install --save express graphql express-graphql
Uma vez que as dependências estejam instaladas, crie o arquivo principal que usaremos, chamado index.js
.
Abra o arquivo index.js
em seu editor de texto preferido.
Agora vamos escrever e explicar o código.
Primeiro, importe os pacotes necessários.
const express = require('express');
const expressGraphQL = require('express-graphql');
const { buildSchema } = require('graphql');
Em seguida, crie um esquema. Um esquema no GraphQL é onde definimos que tipo de ação pode ser executada (por exemplo, Query, Mutation), seu nome e o tipo de dados que ela retorna. Além disso, podemos definir novos tipos de dados.
Query
é usado para buscar informações e Mutation
para modificá-las.
Vamos criar três Query
, uma Mutation
e um novo tipo de dados.
// esquema graphql
const schema = buildSchema(`
type Query {
mensaje: String
persona(id: Int!): Persona
personas(edad: Int!): [Persona]
},
type Mutation {
actualizarEdad(id: Int!, edad: Int!): Persona
},
type Persona {
id: Int,
nombre: String,
apellido: String,
edad: Int,
hobbies: [String]
}
`);
Definimos três Query
: mensaje
, persona
e personas
. Tanto persona
quanto personas
requerem parâmetros. Usamos !
após o tipo de dados para especificar que é um parâmetro obrigatório. persona
retorna um objeto do tipo Persona
e personas
retorna um array de objetos Persona
.
Também definimos uma mutação chamada actualizarEdad
que recebe dois parâmetros do tipo Int
e retorna um objeto Persona
.
Finalmente, definimos um novo tipo de dados chamado Persona
, que contém as propriedades id
, nombre
, apellido
, edad
e hobbies
. hobbies
é definido como [String]
, para que possa conter um array de strings.
Como não estamos usando um banco de dados neste guia, vamos criar um arquivo .json
para armazenar as informações que vamos manipular. Crie um novo arquivo chamado personas.json
.
Adicione as seguintes informações ao arquivo:
[
{
"id": 1,
"nombre": "Carlos",
"apellido": "Rodriguez",
"edad": 21,
"hobbies": ["programar", "cantar", "cine", "dibujar"]
},
{
"id": 2,
"nombre": "Jesus",
"apellido": "Medina",
"edad": 23,
"hobbies": ["cocinar", "música", "cine", "salir"]
},
{
"id": 3,
"nombre": "Karla",
"apellido": "Araúz",
"edad": 18,
"hobbies": ["dibujar", "cocinar", "salir"]
},
{
"id": 4,
"nombre": "Marcos",
"apellido": "Navarro",
"edad": 25,
"hobbies": ["programar", "musica"]
},
{
"id": 5,
"nombre": "Jose",
"apellido": "Mendoza",
"edad": 18,
"hobbies": ["editar videos", "cantar", "tocar guitarra"]
}
]
Agora traga o arquivo para nosso index.js
. O código ficaria assim:
const express = require('express');
const expressGraphQL = require('express-graphql');
const { buildSchema } = require('graphql');
// nova linha
let personas = require('./personas.json');
Agora diga à API GraphQL como buscar as informações definidas no esquema. Para fazer isso, criaremos funções que manipulam o array de objetos personas
que requerimos anteriormente. É importante observar que as modificações feitas nos dados em tempo de execução não modificarão o arquivo personas.json
real, já que estamos usando uma variável temporária para requerer o arquivo.
Aqui está o código com as funções que serão aplicadas ao nosso esquema. Quando uma consulta GraphQL é feita, um objeto de argumentos é recebido. Esses argumentos são os parâmetros enviados com a consulta. Estarei usando desestruturação de objetos
para usar diretamente as propriedades ao criar a função. Mais informações aqui.
// para consultas
const getMensaje = () => 'Hola desde el servidor con graphql';
const getPersona = ({ id }) =>
personas.filter(persona => persona.id === id)[0] || [];
const getPersonas = ({ edad }) =>
personas.filter(persona => persona.edad === edad);
// para mutação
const actualizarEdad = ({ id, edad }) => {
personas.map(persona => {
if (persona.id === id) {
persona.edad = edad;
}
return persona;
});
return getPersona({ id });
};
express-graphql
recebe um objeto com uma propriedade chamada rootValue
. O rootValue
recebe um objeto com os mesmos nomes definidos no esquema e como essas consultas serão processadas.
Vamos criar um objeto chamado root
e passar as funções criadas:
const root = {
mensaje: getMensaje,
persona: getPersona,
personas: getPersonas,
actualizarEdad: actualizarEdad
};
Finalmente, vamos criar o servidor Express com o endpoint /graphql
manipulado por expressGraphQL
:
// criar servidor express com graphql no endpoint /graphql
const app = express();
const port = 4000;
app.use('/graphql', expressGraphQL({
schema: schema,
rootValue: root,
graphiql: true
}));
app.listen(port, () => console.log(`Servidor graphql rodando em http://localhost:${port}/graphql`));
O arquivo index.js
deve ficar assim:
const express = require('express');
const expressGraphQL = require('express-graphql');
const { buildSchema } = require('graphql');
let personas = require('./personas.json');
// esquema graphql
const schema = buildSchema(`
type Query {
mensaje: String
persona(id: Int!): Persona
personas(edad: Int!): [Persona]
},
type Mutation {
actualizarEdad(id: Int!, edad: Int!): Persona
},
type Persona {
id: Int,
nombre: String,
apellido: String,
edad: Int,
hobbies: [String]
}
`);
// para consultas
const getMensaje = () => 'Hola desde el servidor con graphql';
const getPersona = ({ id }) =>
personas.filter(persona => persona.id === id)[0] || [];
const getPersonas = ({ edad }) =>
personas.filter(persona => persona.edad === edad);
// para mutação
const actualizarEdad = ({ id, edad }) => {
personas.map(persona => {
if (persona.id === id) {
persona.edad = edad;
}
return persona;
});
return getPersona({ id });
};
const root = {
mensaje: getMensaje,
persona: getPersona,
personas: getPersonas,
actualizarEdad: actualizarEdad
};
// criar servidor express com graphql no endpoint /graphql
const app = express();
const port = 4000;
app.use('/graphql', expressGraphQL({
schema: schema,
rootValue: root,
graphiql: true
}));
app.listen(port, () => console.log(`Servidor graphql rodando em http://localhost:${port}/graphql`));
Execução
Para executar nosso servidor, execute o seguinte comando no console dentro do projeto:
$ node index.js
Ao navegar para http://localhost:4000/graphql, você deve ver a seguinte página:
Temos acesso a um painel gráfico para interagir com nossa API, já que definimos graphiql: true
ao criar o endpoint.
Testando com o GraphiQL
Se colocarmos { mensaje }
no lado direito, a API deve mostrar o seguinte resultado:
Também podemos passar parâmetros para nossa consulta. Por exemplo, podemos buscar persona
com id: 1
e especificar quais propriedades queremos obter da seguinte forma:
Vemos que estamos apenas mostrando as propriedades id
, nombre
e hobbies
.
Também podemos usar a Query
que criamos chamada personas
que recebe uma idade.
Para executar uma mutação, devemos primeiro defini-la como tal. Neste caso, definimos uma mutação chamada actualizarEdad e especificamos que ela deve ter id
e edad
do tipo Int
. Veremos que após executar a mutação, a função que definimos retorna o objeto onde as informações de idade modificadas podem ser vistas.
Agora vamos mudar a idade de Carlos
de 21
para 18
executando a mutação que criamos:
Deve-se observar que, como definimos uma mutação com variáveis $id
e $edad
, é necessário defini-las na parte inferior onde diz Query Variables
.
Se consultarmos a consulta personas
novamente com a idade 18
, veremos que agora Carlos
aparece na lista:
Conclusões
Com esses exemplos, vemos que o GraphQL nos fornece um ambiente gráfico onde podemos testar nossos esquemas e processos. Especificamente, no nosso caso, pudemos empregar vários conceitos do GraphQL, como esquemas, métodos que os resolvem e sua configuração em um servidor Express.
Espero que este guia seja útil para você. Até mais!