Criando um servidor GraphQL pronto para produção em 5 minutos
Provavelmente, você já ouviu falar de GraphQL, certo?
Quando decidi parar para estudar a tecnologia, em poucas horas, cheguei à seguinte conclusão:
GraphQL é uma das coisas mais inteligentes que já vi nesse mundinho Dev. Difícil ver uma tecnologia ser tão fácil e intuitiva
— Jaydson Gomes (@jaydson) October 24, 2017
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.
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
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 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:$PG_PASS@$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', 'john.smith@email.com'), (2, 'sara', '1234', 'Sara Smith', 'sara.smith@email.com'), (3, 'budd', '1234','Budd Deey', 'budd.deey@email.com'), (4, 'kathryn','1234','Kathryn Ramirez', 'kathryn.ramirez@email.com'), (5, 'joe','1234','Joe Tucker', 'joe.tucker@email.com'), (6, 'jaydson','1234','Jaydson Gomes', 'jaydson@nasc.io'); 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
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
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 todos posts de um usuário
{ userAccountById(id:6) { name postsByUserId { edges { node { title } } } } }
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
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.