Skip to content

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 portanto npm 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.

bash
$ mkdir express-gql
$ cd express-gql

Vamos inicializar o projeto com npm usando npm init. Preencha as opções solicitadas.

bash
$ 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.

bash
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:

bash
$ 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.

javascript
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.

javascript
// 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:

json
[
  {
    "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:

javascript
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.

javascript
// 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:

javascript
const root = {
  mensaje: getMensaje,
  persona: getPersona, 
  personas: getPersonas,
  actualizarEdad: actualizarEdad
};

Finalmente, vamos criar o servidor Express com o endpoint /graphql manipulado por expressGraphQL:

javascript
// 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:

javascript
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:

bash
$ node index.js

Ao navegar para http://localhost:4000/graphql, você deve ver a seguinte página:

Página inicial do Express GraphQL

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:

Página inicial do Express GraphQL

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:

Página inicial do Express GraphQL

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.

Página inicial do Express GraphQL

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:

Página inicial do Express GraphQL

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:

Página inicial do Express GraphQL

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!