Criando um servidor GraphQL pronto para produção em 5 minutos

Em:

Provavelmente, você já ouviu falar de GraphQL, certo?
Quando decidi parar para estudar a tecnologia, em poucas horas, cheguei à seguinte conclusão:

GraphQL é uma linguagem de consultas (query language), assim como o velho conhecido SQL.
Entretanto, o foco do GraphQL são APIs.
Com GraphQL o poder está no cliente, de maneira que é possível pedir exatamente o necessário em uma consulta, resultando em produtividade, autonomia e performance.
Evoluir APIs com GraphQL se torna muito mais fácil, pois não existe a necessidade de criação de novas rotas ou end-points.
Outro detalhe poderoso do GraphQL é a possibilidade do surgimento de novas ferramentas para desenvolvedores.

screenshot-2017-11-3-graphql-a-query-language-for-apis-2

Não vamos cobrir os detalhes da tecnologia neste post.
Sendo assim, o ideal é que o leitor já tenha conhecimento prévio de GraphQL.
Como dito anteriormente, poucas horas de estudo já serão o suficiente.

Neste post, vamos criar um servidor GraphQL do zero e colocá-lo em produção.
Ah… um detalhe importante: vamos fazer isso em cinco minutos 🙂

Requisitos básicos

👉 Conhecimento básico de GraphQL
👉 Conhecimento básico de SQL e modelagem de banco de dados
👉 Conhecimento básico do banco de dados open source Postgres
👉 Conhecimento básico de Node.js
👉 Conhecimento básico de ferramentas de linha de comando
👉 Conhecimento básico de serviços Amazon
👉 Node.js e Postgres instalado

Minuto um

Vamos criar uma aplicação clássica, um sistema de blog.
A ideia é que, a partir deste exemplo, você consiga aplicar todos os passos utilizando a modelagem da sua aplicação.
Para o nosso super blog, vamos precisar de algumas entidades relacionais:

[user_account]
Esta entidade representa um usuário no blog. Ele pode ser um autor ou leitor

[post]
Post é o artigo/texto do blog

[comment]
Cada post pode conter n comentários

Diagrama ER do nosso exemplo de aplicação

Diagrama ER do nosso exemplo de aplicação

Utilizaremos o excelente banco de dados Postgres para armazenar os dados do nosso blog.
Para o banco de dados, vou usar Amazon RDS, que é uma solução de database as a service, mas você pode utilizar qualquer outra solução.
Crie um banco de dados de teste e execute o schema abaixo para criar as tabelas mapeadas para o nosso sistema.

CREATE TABLE user_account (
    id serial PRIMARY KEY,
    username VARCHAR (50) UNIQUE NOT NULL,
    password VARCHAR (50) NOT NULL,
    name VARCHAR (50) NOT NULL,
    email VARCHAR (355) UNIQUE NOT NULL,
    created_on TIMESTAMP NOT NULL DEFAULT now(),
    last_login TIMESTAMP
);

CREATE TABLE post (
    id serial PRIMARY KEY,
    user_id INTEGER NOT NULL,
    title VARCHAR (100) NOT NULL,
    content TEXT NOT NULL,
    created_on TIMESTAMP NOT NULL DEFAULT now(),
    CONSTRAINT user_fkey FOREIGN KEY (user_id)
    REFERENCES user_account (id) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION
);

CREATE TABLE comment (
    id serial PRIMARY KEY,
    post_id integer NOT NULL,
    user_id integer NOT NULL,
    content TEXT NOT NULL,
    created_on TIMESTAMP NOT NULL DEFAULT now(),
    CONSTRAINT user_fkey FOREIGN KEY (user_id)
    REFERENCES user_account (id) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION,
    CONSTRAINT post_fkey FOREIGN KEY (post_id)
    REFERENCES post (id) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION
);

Note as relações entre as entidades:
Cada post possui referência ao user_account, estabelecendo uma relação de 1 > 1, onde – basicamente – estamos dizendo que um post no blog possui um usuário.
Cada comment possui referência ao user_account e ao post, estabelecendo uma relação de 1 > N (post > commment) e 1 > 1 (comment > user), em que estamos dizendo que um post no blog pode conter n comentários e que cada comentário veio de um usuário.

Minuto dois

Agora, entramos na parte mais legal, a modelagem da nossa API GraphQL.
E digo que é a parte mais legal, pois não vamos precisar fazer a modelagem.
Mas como assim, Jaydson?
Isso mesmo! Com um bom banco de dados modelado, conseguimos inferir as entidades e relações com o PostGraphQL.
O PostGraphQL cria um schema por reflexão em um banco de dados Postgres.
Isso quer dizer que podemos focar em construir nosso banco de dados da melhor maneira possível e, após isso, ter uma API GraphQL na ponta preparada para a sua aplicação.
Legal, né? Mas como fazer?

Seguindo a promessa dos cinco minutos, vamos agora instalar e levantar o servidor GraphQL em nosso ambiente.
Primeiramente, crie uma pasta e inicie um projeto npm.

mkdir super-blog
cd super-blog
npm init

Agora, instale o PostGraphQL como dependência:

npm install postgraphql --save
Resultado após instalar o PostGraphQLResultado após instalar o PostGraphQL

Resultado após instalar o PostGraphQL

O seu package.json deve ficar parecido com este:

{
  "name": "super-blog",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "postgraphql": "^3.5.0"
  }
}

Agora, adicione o comando start aos scripts npm. Esse comando irá iniciar o nosso servidor GraphQL.

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "postgraphql -c postgres://$PG_USER:[email protected]$PG_HOST:$PG_PORT/$PG_DBNAME"
 }

Por medida de segurança, não vamos expor os dados de acesso do nosso servidor e nem deixá-los versionados em repositórios (GitHub, Bitbucket).
O comando start receberá por parâmetro as variáveis de conexão.
Exemplo:

PG_USER=user PG_PASS=pass PG_HOST=host PG_PORT=port PG_DBNAME=db npm start

Minuto três

Vamos adicionar alguns dados no nosso banco de dados para poder testar a API GraphQL.

begin;

insert into user_account (id, username, password, name, email) values
  (1, 'johnsmith','1234','John Smith', '[email protected]'),
  (2, 'sara', '1234', 'Sara Smith', '[email protected]'),
  (3, 'budd', '1234','Budd Deey', '[email protected]'),
  (4, 'kathryn','1234','Kathryn Ramirez', '[email protected]'),
  (5, 'joe','1234','Joe Tucker', '[email protected]'),
  (6, 'jaydson','1234','Jaydson Gomes', '[email protected]');

insert into post (id, user_id, title, content) values
  (1, 6, 'Meu primeiro post','Loren Ipsun Dolor 1'),
  (2, 6, 'Meu segundo post','Loren Ipsun Dolor 2'),
  (3, 6, 'Meu terceiro post','Loren Ipsun Dolor 3'),
  (4, 6, 'Meu quarto post','Loren Ipsun Dolor 4'),
  (5, 6, 'Meu quinto post','Loren Ipsun Dolor 5');

insert into comment (id, post_id, user_id, content) values
  (1, 1, 1, 'Muito legal esse post'),
  (2, 1, 2, 'Verdade, muito legal!'),
  (3, 1, 3, 'Eu achei mais ou menos'),
  (4, 2, 1, 'Muito bom!'),
  (5, 2, 5, 'Show'),
  (6, 4, 4, 'Interessante o post!');

commit;

Minuto quatro

Agora, vamos levantar o nosso servidor GraphQL em produção.
Como o servidor GraphQL é uma simples aplicação Node.js, vou utilizar o now para subir o serviço.
Será necessário criar uma conta no now e ter a ferramenta de linha de comando instalada:

npm install -g now

Agora, vamos colocar a nossa API no ar:

now -e PG_USER="user" -e PG_PASS="pass" -e PG_HOST="sua_url.rds.amazonaws.com" -e PG_PORT="5432" -e PG_DBNAME="superblog"

O now suporta que variáveis de ambiente sejam passadas durante o deploy, de maneira que o nosso script de start irá capturar estas variáveis e iniciar o serviço.
Não esqueça de substituir corretamente as variáveis, de acordo com os seus dados de acesso.

Se tudo deu certo, o output será algo parecido com a imagem a seguir:

Fazendo deploy do servidor GraphQL no now

Fazendo deploy do servidor GraphQL no now

Minuto cinco

Agora, vamos ver se está tudo funcionando mesmo.
Ao fazer o deploy no now, geramos a seguinte URL: https://super-blog-fgqbrohgrb.now.sh/
Nosso servidor está ativo neste endereço e, para testar, vamos usar o GraphiQL, uma ferramenta para fazer queries e também testar sua API GraphQL.
Com relação ao PostGraphQL, não precisamos fazer mais nada, pois já temos uma rota para conseguir testar nossa API: /graphiql.
Deixei a URL pública, assim vocês podem testar o exemplo que utilizamos neste post: https://super-blog-fgqbrohgrb.now.sh/graphiql

GraphiQL, ferramenta para testar nossa API GraphQL

GraphiQL, ferramenta para testar nossa API GraphQL

O PostGraphQL fez o mapeamento do nosso banco de dados e deixou a API GraphQL pronta para consumo. Vamos ver alguns exemplos:

Listando todos os posts

{
  allPosts {
    edges {
      node {
        id
        title
      }
    }
  }
}
Listando posts com a API GraphQL

Listando posts com a API GraphQL

Listando todos posts de um usuário

{
  userAccountById(id:6) {
    name
    postsByUserId {
      edges {
        node {
          title
        }
      }
    }
  }
}
Listando posts de um usuário

Listando posts de um usuário

Listando todos comentários de um post específico de um usuário específico

{
  userAccountById(id:6) {
    name
    postsByUserId(condition: {id:1}) {
      edges {
        node {
          title
          content
          commentsByPostId {
            edges {
                    node {
                content
              }
            }
          }
        }
      }
    }
  }
}
Todos comentários de um post de um usuário

Todos comentários de um post de um usuário

Conclusão

O PostGraphQL se mostrou uma ferramenta muito interessante, pois abstrai o mapeamento entre o banco de dados e a sua API.
A API GraphQL gerada das relações entre as entidades é muito útil e permite que, rapidamente, seja criada uma aplicação consumindo-a.
Podem existir casos em que o mapeamento feito pelo PostGraphQL não atenda totalmente às necessidades da sua aplicação. Neste caso, o PostGraphQL possibilita a criação de procedures no Postgres. Estas procedures são mapeadas diretamente para a sua API GraphQL, dando um poder enorme para o desenvolvedor.

A abordagem de se criar uma aplicação iniciando pela API (api first) já é uma técnica bem conhecida e difundida entre desenvolvedores de software.
Com GraphQL, isso se torna ainda mais interessante. Poder evoluir a API sem a necessidade de controle de versões é – de fato – um ponto muito positivo.

  • Weekly #218 – Novidades no Node.js 9, JS de 60 Milhões, DevSummit e GraphQL em produção

    Muitas novidades e artigos nesta edição! Os meninos falam sobre algumas coisas legais do Node.js 9, comentam sobre GraphQL e ainda sobre como foi o ChromeDevSummit 2017.

  • Sons para focar no trabalho

    Vivemos na era da informação e da distração. É tanto conteúdo para se consumir que, em alguns momentos, é fácil perder o foco. Eu, pessoalmente, gosto mesmo é de ouvir música enquanto trabalho. Sendo mais preciso, um bom e velho Rock ‘n Roll. Mas existem algumas alternativas interessantes para quem não gosta ou não consegue […]

  • React: do básico ao avançado – Parte 4

    React é uma biblioteca JavaScript para desenvolvimento de interfaces de usuário. Esta é a quarta parte de uma série de artigos que ensina a desenvolver e estruturar aplicações com JavaScript e React. Clique aqui caso você ainda não tenha lido a terceira parte. Na parte anterior, aprendemos o que React soluciona e como ele soluciona. […]

Patrocinadores BrazilJS

Gold

Silver

Bronze

Apoio

BrazilJS® é uma iniciativa NASC.     Hosted by Getup