Postado em 13 de setembro de 2023

Manage Links – Next, Prisma and GraphQL

Atalhos

Disclaimer

Este projeto é didático e fui submetido a uma entrevista de emprego e quero construir uma maior familiaridade com GraphQL pois foi um dos requisitos.

Usaremos:

  • NEXT.js
  • Prisma
  • GraphQL
  • TypeScript
  • Apollo

Vou ser objetivo neste tutorial para não perder muito tempo, então não espere eu escrever grandes textos para explicar coisas mais simples.

1 - Iniciando o projeto

Entre no diretório através do terminal

 

  • npx create-next-app –typescript
  • Dê um nome ao seu projeto e adicione o que desejar
  • Finalize e abra o projeto no seu editor

2 - Adicionando o Prisma

  • yarn add -D prisma
  • yarn add @prisma/client

3 - Rodando o Prisma

  • npx prisma init

4 - Crie seu Banco de Dados

Já tenho o PostgreSQL instalado somente vou criar um novo DB

5 - Conectando o DB ao Prisma

Modifique esta variavel no arquivo .env na raiz do seu projeto

  • DATABASE_URL=”postgresql://SEUUSUARIO:SUASENHA@localhost:PORTA/NOMEDOBANCO?schema=public”

6 - Construindo o schema no prisma

O schema são as tabelas do banco, vá na pasta prisma/schema.prisma

  • Aqui não tem muito o que fazer para aprender é ir na documentação e ver como criar o que você precisa
  • https://www.prisma.io/

O meu ficou assim:

model Link {
  id    Int    @id @default(autoincrement())
  title String
  url   String
  @@map(“links”)
}

7 - Enviando a estrutura do schema para o banco

  • npx prisma db push (para enviar do código para o DB)
  • npx prisma db pull (para enviar do DB para o código)

8 - Enviando dados fakes para o banco

  • criei na raiz do projeto um arquivo fakedata.js e dentro dele joguei o script abaixo:
  • Agora na cli rode node fakedata.js e pronto os dados devem ser inseridos no banco
  • Após inserir apague o arquivo só serve para esta finalidade

const { PrismaClient } = require(‘@prisma/client’);

const prisma = new PrismaClient();

async function seedDatabase() {
try {

const links = [
{ title: ‘Link 1’, url: ‘https://www.example.com/link1’ },
{ title: ‘Link 2’, url: ‘https://www.example.com/link2’ },
{ title: ‘Link 3’, url: ‘https://www.example.com/link3’ },
{ title: ‘Link 4’, url: ‘https://www.example.com/link4’ },
{ title: ‘Link 5’, url: ‘https://www.example.com/link5’ },
];

for (const link of links) {
await prisma.link.create({
data: link,
});
}

console.log(‘Dados fictícios inseridos com sucesso!’);
} catch (error) {
console.error(‘Erro ao inserir dados fictícios:’, error);
} finally {
await prisma.$disconnect();
}
}

seedDatabase();

9 - Mudando a estrutura da Tabela

Caso precise mudar a estrutura da tabela por algum motivo rode após a alteração

  • npx prisma generate

Este comando tambem cria o Prisma Client, mas ele já foi criado anteriormente pra gente com o push, foi mais pra mostrar pra vocês este comando.

10 - Instalando o GraphQL & Apollo

Rode o comando

  • yarn add graphql apollo-server-micro micro micro-cors

Como instalamos microservices vamos ter que add eles no typescript

  • yarn add -D @types/micro-cors

11 - Configurando o GraphQL

  • Crie uma pasta graphQL na raiz
  • Dentro dela crie três aquivos, typeDefs.ts, resolvers.ts, context.ts

Conteudo do arquivo typeDefs.ts

import { gql } from ‘apollo-server-micro’;
export const typeDefs = gql`
type Query {
  links: [Link]
}
type Link {
  id: ID
  title: String
  url: string
}

`;

Conteudo do arquivo resolver.ts

export const resolvers = {
  Query: {
    links: async (parent, args, context) => await context.prisma.link.findMany()
  }

}

Conteudo do arquivo context.ts – Voltaremos aqui

12 - Criando as conexões do Prisma para o Contexto

Precisamos criar conexões isoladas do contexto pois poderemos utilizar estas conexões em outros lugares da aplicação, por isso tem que está fora do Context.ts

  • Crie uma pasta na raiz do projeto chama libs e dentro um arquivo prisma.ts

Conteudo do arquivo prisma.ts

import { PrismaClient } from ‘@prisma/client’;
declare global {
  var prisma: PrismaClient | undefined;
}
export const prisma = global.prisma || new PrismaClient();
if(process.env.NODE_ENV !== ‘production’) {
  global.prisma = prisma;
}
export default prisma;

13 - Editando o arquivo graphQL/context.ts

Agora sim vamos editar ele pois ele vai utilizar a variável que criamos para dentro do contexto:

import { PrismaClient } from ‘@prisma/client’;
import prisma from ‘../libs/prisma’;
export type Context = {
  prisma: PrismaClient;
}
export const context: Context = { prisma }

14 - Resolvendo um problema em typeDefs.ts

Você deve ter observado que deu erro no apollo-server-micro pois ele foi descontinuado, fui verificar na documentação:

https://www.npmjs.com/package/apollo-server-micro

Então é necessário instalar o @apollo/server para resolver o problema:

  • yarn add @apollo/server

Realmente espero que não dê mais problemas, porém se der logo a frente a gente resolve.

15 - O arquivo resolver.ts tem problemas de tipagens

Bom vamos resolver estes problemas e para isso vamos instalar o @graphql-codegen/cli para conseguir gerar essas tipagens automaticamente dentro do graphql e a gente nao se preocupar tanto com isso.

  • yarn add @graphql-codegen/cli

para isso funcionar teremos que configurar o graphql-codegen

16 - Instalando o graphql-codegen

A configuração é por CLI e precisamos dizer aonde o código está e aonde ele vai criar as types.

  • npx graphql-codegen init

Respondi desta forma todas as perguntas

? What type of application are you building? Backend – API or server
? Where is your schema?: (path or url) ./graphql/typeDefs.ts
? Pick plugins: TypeScript (required by other typescript plugins)
? Where to write the output: ./grapgql/resolvers-types.ts
? Do you want to generate an introspection file? No
? How to name the config file? codegen.ts
? What script in package.json should run the codegen? codegen

Após isto será gerado todos os arquivos

17 - Configurando o graphql-codegen

Vá no arquivo codegen.ts gerado na raiz do projeto e deixe assim

import type { CodegenConfig } from ‘@graphql-codegen/cli’;
const config: CodegenConfig = {
  overwrite: true,
  schema: “./graphql/typeDefs.ts”,
  generates: {
    “./grapgql/resolvers-types.ts”: {
      plugins: [“typescript”, “typescript-resolvers”]
    }
  }
};
export default config;

18 - Instalando o typescript-resolvers

Rode

  • yarn install
  • yarn add -D @graphql-codegen/typescript-resolvers

19 - Agora vamos rodar o codegen

O comando é codegen como configuramos anteriormente, então rode

  • yarn codegen

Deu erro =/

20 - Corrigindo o primeiro erro

O erro:

$ yarn codegen
yarn run v1.22.19
warning package.json: “dependencies” has dependency “@graphql-codegen/cli” with range “^5.0.0” that collides with a dependency in “devDependencies” of the same name with version “5.0.0”
warning ..\..\..\package.json: No license field
$ graphql-codegen –config codegen.ts
✔ Parse Configuration
⚠ Generate outputs
❯ Generate to ./grapgql/resolvers-types.ts

Failed to load schema from ./graphql/typeDefs.ts:

Unknown type: “string”.
Error: Unknown type: “strin…
◼ Load GraphQL documents
◼ Generate
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

O erro está destacado

  • Para corrigir vá em codegen.ts, estará em generates, corrija o path
  • Rode o comando novamente

Deu erro novamente =/

20 - Corrigindo o segundo erro

O erro:

$ yarn codegen
yarn run v1.22.19
warning package.json: “dependencies” has dependency “@graphql-codegen/cli” with range “^5.0.0” that collides with a dependency in “devDependencies” of the same name with version “5.0.0”
warning ..\..\..\package.json: No license field
$ graphql-codegen –config codegen.ts
✔ Parse Configuration
⚠ Generate outputs
❯ Generate to ./graphql/resolvers-types.ts

Failed to load schema from ./graphql/typeDefs.ts:

Unknown type: “string”.
Error: Unknown type: “strin…
◼ Load GraphQL documents
◼ Generate
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

O erro está destacado

  • Para corrigir vá em graphql/typeDefs.ts
  • Acabei escrevendo url: string com s minúsculo, coloque o S maiúsculo por favor.
  • Rode o comando novamente

21 - Uff deu certo GraphQL Criado 🥵

$ yarn codegen
yarn run v1.22.19
warning package.json: “dependencies” has dependency “@graphql-codegen/cli” with range “^5.0.0” that collides with a dependency in “devDependencies” of the same name with version “5.0.0”
warning ..\..\..\package.json: No license field
$ graphql-codegen –config codegen.ts
✔ Parse Configuration
✔ Generate outputs
Done in 1.48s.

  • Agora o arquivo resolvers-types.ts foi gerado junto dos types

22 - Criando API do GraphQL

  • Eu criei dentro de src uma pasta chamada pages e dentro dela uma pasta chamada api e dentro dela graphql.tsx
  • Se você instalou o projeto sem a source crie aonde desejar.

O arquivo é grande vou colocar ele para download será melhor – Faça download aqui

Este código configura um servidor Apollo GraphQL em uma API Next.js e lida com solicitações GraphQL na rota “/api/graphql”.

23 - Finalizada a API com GraphQL

Agora rode um yan dev

  • Abra o projeto na porta configurada, meu caso localhost:3000
  • Em seguida acesse localhost:3000/api/graphql
  • Pronto agora o apolo deve estar rodando
  • Clique em Query Your Server e divirta-se

Repositório do projeto

Fique a vontade para clonar e testar =)