GraphQL + Typescript - Parte I

Eduardo Pacheco Celeste
beyondTest
Published in
8 min readDec 15, 2020

Escrevendo uma API com GraphQL e Typescript do zero!

Typescript + GraphQL

Por que Typescript?

Criado em 2012 pela Microsoft para criar aplicações Javascript de grande escala, o Typescript é um super conjunto que visa melhorar a produtividade daqueles que trabalham com Javascript. Dentre as principais funcionalidades que o Typescript nos proporciona podemos citar:

  • Validação de código e expressões em tempo de compilação evitando que os erros sejam encontrados apenas durante a execução do projeto.
  • Tipagem estática (como no Java por exemplo) que torna as aplicações mais robustas e menos suscetíveis a erros.
  • É possível escrever aplicações tanto no server-side quanto no client-side.

Um ponto importante e que vale se destacar é que código escrito em TS será utilizado apenas no ambiente de desenvolvimento. Ao fim do desenvolvimento, o código será transpilado para JS em ambiente produtivo.

Para saber mais sobre TS há um artigo bem completo do Eduardo Rabelo que conta em detalhes todas as suas features (Typescript 3.1).

Por que GraphQL?

GraphQL é uma linguagem de consulta de dados desenvolvida pelo Facebook em meados de 2015. Ele possui algumas características interessantes que o diferem do protocolo mais utilizado atualmente que é o REST, como por exemplo:

  • Performance - Através do GraphQL podemos solicitar apenas os dados que precisamos. Isso evita que dados que serão descartados não precisem trafegar entre servidor/cliente (Overfetching - é quando nos é retornado mais dados do que precisamos pra realizar alguma ação).
  • Os tipos de dados são bem definidos, o que reduz as falhas de comunicação entre o cliente e o servidor.
  • Facilita na agregação de diferentes fontes de dados.

O GraphQL pode ser dividido em dois principais pilares: Schemas e Resolvers. Vamos falar mais detalhadamente deles na sequência do artigo.

Pré-Requisitos

Para que todas as etapas do tutorial possam ser executadas com sucesso é necessário a instalação/configuração dos seguintes softwares:

  • IDE de Desenvolvimento (Fica a critério de vocês a utilização da que vocês se sentirem mais confortáveis, no meu caso estou utilizando o VSCode)
  • Node e NPM/Yarn (Este artigo na seção de pré-requisitos possui alguns links que vão auxiliar na instalação de ambos)
  • Conhecimento básico em Javascript/Typescript
ObservaçãoUm ponto importante é de que os comandos apresentados abaixo serão os utilizados em ambientes UNIX. Como há algumas diferenciações pra usuários Windows, caso tenham algum tipo de dificuldade basta acessarem esse link que tem um de/para entre os comandos: https://www.geeksforgeeks.org/linux-vs-windows-commands/

Iniciando uma aplicação com Typescript

Para iniciar uma aplicação utilizando TS é bem simples, basta criarmos um diretório e nele executarmos o seguinte comando:

$ mkdir ts-graphql && cd ts-graphql && npm init -y && npm i typescript -D

Este comando apesar de extenso é bem simples. Ele cria um diretório → vai até esse diretório → inicializa o projeto → e instala nossa primeira dependência.

O resultado será a criação de dois arquivos e uma pasta. Agora precisamos inicializar o nosso projeto como sendo um projeto em Typescript, pra isso basta executarmos o seguinte comando:

$ node_modules/typescript/bin/tsc --init

E agora um novo arquivo (tsconfig.json) foi criado na raiz do nosso projeto.

Este novo arquivo vem com várias chaves/valores e suas respectivas descrições. Para o nosso caso vamos apagar o conteúdo do arquivo inteiro e substituir pelo seguinte:

{
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"strict": false,
"outDir": "./dist",
"sourceMap": true,
"rootDir": "src",
"baseUrl": ".",
"paths": {
"*": [
"node_modules/*"
]
}
}
}

E pronto! Temos a configuração básica pra escrevermos nosso projeto com Typescript :)

Instalando/Configurando as demais dependências

Precisamos agora instalar as demais bibliotecas que nos auxiliarão no restante do projeto. Para isso executar o seguinte comando (o comando touch pode ser substituído por um equivalente do Windows mostrado aqui):

$ npm i graphql-yoga && npm i -D @types/ws nodemon ts-node && touch nodemon.json

Após a execução do comando um novo arquivo será criado na raiz do projeto (nodemon.json). Para este adicionar o seguinte conteúdo e salvar:

{
"watch": ["src"],
"ext": "ts",
"ignore": [
"dist",
"node_modules"
],
"exec": "ts-node --files ./src/server.ts"
}

Por fim temos apenas outras duas etapas. A primeira é a de criarmos na raiz do projeto uma nova pasta chamada src e dentro desta pasta um arquivo chamado server.ts

O conteúdo do arquivo server.ts apenas para fins de teste será o seguinte:

const graphql = 'GraphQL';export function message(): string {
return `Learning Typescript and ${graphql}! `;
};
console.log(message());

Já a última etapa dessa seção é a de criarmos um script dentro do arquivo package.json que se encarregará de ler o que foi definido no arquivo server.ts

"scripts": {
"dev": "nodemon"
},

Se tudo estiver correto, ao executar o comando abaixo:

$ npm run dev

O output no terminal deverá ser algo como o mostrado abaixo:

Step — Instalando/Configurando as demais dependências

Estruturando e criando nossa primeira Query no GraphQL

Agora que temos as dependências necessárias para a criação do projeto, vamos começar a estruturá-lo.

Primeiramente podemos apagar o conteúdo do arquivo server.ts criado anteriormente uma vez que este foi escrito apenas para exemplificar a inicialização do projeto.

Iremos também criar um novo arquivo, dessa vez chamado animals.ts no mesmo nível do arquivo server.ts.

O arquivo server.ts terá como responsabilidade inicializar o servidor do GraphQL. O snippet abaixo contém o conteúdo do arquivo e mais abaixo o que faz cada parte do arquivo:

  1. Na linha 1 importamos a library graphql-yoga que será o responsável por iniciar o server.
  2. Na linha 3 importamos duas constantes (que ainda irão ser criadas no arquivo animals.ts).
  3. Na linha 5 instanciamos o GraphQLServer com as constantes importadas anteriormente e atribuímos o resultado a variável server.
  4. Da linha 7 a linha 11 é onde de fato inicializamos o servidor.

Uma vez que o server.ts esta configurado, vamos para o principal arquivo do artigo que é onde iremos consultar/modificar os dados. No arquivo animals.ts iremos ter o seguinte conteúdo:

  1. Onde da linha 1 a linha 21 declaramos um simples array de objetos.
  2. Da 23 a 31 é onde atribuímos o tipo de dado na qual iremos poder consultar/manipular posteriormente (schema).
  3. E por fim criamos um simples resolver que com base no tamanho do array animals seleciona de maneira randômica um animal da lista.

Com isso podemos testar nossa aplicação antes de seguirmos para a próxima etapa. Para isso novamente rodar o comando:

$ npm run dev

E agora quando acessarmos a url http://localhost:4000/ podemos consultar a nossa API em GraphQL através do playground utilizando a seguinte query (Para executar basta clicar no símbolo de play):

Playground

O legal é que caso queiramos apenas a chave emoji basta alterarmos a query para:

query {
whatsAnimal {
emoji
}
}

Ou seja, as queries são totalmente customizáveis com base na necessidade daquele que irá consumir os dados!

Trabalhando com as Mutations

Conforme visto na seção anterior, podemos fazer consultas customizáveis de uma forma bem simples no GraphQL através das queries.

Porém diferente de uma API REST que possui N verbos distintos (GET, PUT, POST, DELETE, etc) no GraphQL só existem dois tipos: as queries para as consultas e as mutations para a manipulação dos dados.

Nota:Além das queries e mutations existe também as subscriptions que não serão abordadas nesta primeira parte do artigo. Caso queiram mais informações, segue um link para estudo: https://blog.logrocket.com/graphql-subscriptions-with-node-js/

Assim como as queries as mutations irão ficar também hospedadas no arquivo animals.ts. Segue abaixo snippet do código com um exemplo de mutations para adicionar um novo animal e outra para remover caso exista:

  1. Na linha 1 alteramos o array que foi declarado como um const para um let (assim o mesmo poderá sofrer variações).
  2. Da linha 28 a 42 declaramos os nossos schemas (note que agora o type Animal pode retornar um ID também). Além disso criamos mais uma query (essa irá retornar todos os animais cadastrados) e as nossas mutations (que poderão manipular os dados, inserindo e excluindo os animais).
  3. Já da linha 44 a 79 é onde esta a business logic do nosso projeto. A segunda query é bem simples e só retorna o array de animais (foi criada para testarmos se a mutations irão funcionar conforme o esperado).
  4. A primeira mutation é a de inclusão, nela verificamos o tamanho do array para gerarmos um novo ID único e depois o inserimos no array de animais.
  5. A segunda mutation irá excluir com base no ID do animal. Para isso é realizado um filtro pra ver se tal ID existe já no array e caso existir é feito um filtro retornando o animal já removido da listagem.

Uma vez que tudo foi configurado basta testarmos o nosso projeto :)

Para isso basta acessarmos novamente o nosso playground e agora manipularmos os registros através das mutations:

  • Para criar um novo registro de animal:
mutation {
createAnimal(animal: "frog", emoji: "🐸") {
id
emoji
}
}
  • Para consultar todos os registros após a inclusão:
query {
allAnimals {
id
animal
emoji
}
}
  • Para deletar um registro:
mutation {
deleteAnimal(id: "5") {
animal
}
}

Considerações Finais

Como vimos é bem simples o funcionamento de uma API utilizando GraphQL. Basta entendermos o conceito de schemas e resolvers e de que dentro destes iremos inserir nossas queries e mutations.

Porém é notório que para este nosso exemplo não seguimos quaisquer pattern e que negligenciamos alguns dos principais benefícios que o Typescript nos fornece. Por isso a ideia é evoluirmos este projeto para algo mais próximo de um projeto real.

A ideia é estruturarmos melhor os arquivos, seguirmos algum pattern recomendável, criarmos alguns testes e usufruirmos de frameworks que nos auxiliem em escrever em conjunto com o Typescript. Mas isso fica para um(?) próximo artigo.

Ah e caso queiram baixar o projeto como exemplo, segue: https://github.com/eduardopc/ts-graphql/tree/first-part-graphql-typescript

Links e Referências

--

--