Este texto é sobre minha experiência tentando replicar a geração de código (e tipos) para interações entre **frontend e backend, se você prefere partir pro código, pode pular pra parte da implementação.
Conteudo:
Há uns anos atras, trabalhei em um projeto GraphQL, eu amei demais as vantagens dele (apesar de reconhecer alguns de seus defeitos), mas uma das que mais se destacou foi a de ter um schema de tudo que o backend disponibiliza como API, o schema no GraphQL é algo assim:
type Query {
me: User
}
type User {
id: ID
name: String
}
No GraphQL, o schema informa todos os 'endpoints' de consulta disponíveis (type Query
), suas rotas (me
) , argumentos (se tiverem) e retornos (User
). Além de ser uma documentação, o schema também me possibilita gerar código. **Por exemplo, aplicando o graphql-code-generator no schema acima eu consigo gerar um código similar a este em Typescript:
type Query = {
me: User
}
type User = {
id: string
name: string
}
Porém quando precisei voltar a mexer em REST, lembrei que não era costume fazer essa geração de código, e, além disso, eu não conhecia muito sobre como documentar/formalizar APIs RESTful, mas eu me lembrava de já ter lidado com o Swagger pra isso.
Se você trabalha com REST com certeza já ouviu falar do Swagger, ele é uma ferramenta que te permite gerar uma página interativa com a documentação da sua API REST, uma das coisas que você pode não ter pensado é que o Swagger não foi feito pra ser usado somente com uma UI.
O Swagger é baseado em uma especificação, chamada de OpenAPI Specification (OAS), dela ele gera a sua interface amigável. Geralmente a OAS é escrita ou gerada em JSON e te permite fazer as mesmas coisas que você faria com o schema GraphQL: documentar toda a sua API e também gerar 'coisas' com base nela. Um exemplo da especificação OAS fica assim:
{
"openapi": "3.0.0",
"info": {
"title": "My API Documentation",
"description": "My API documentation and playground",
"version": "1.0",
"contact": {}
},
"components": {
"schemas": {
"User": {
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" }
},
"required": ["id", "name"]
}
}
},
"paths": {
"/me": {
"get": {
"operationId": "getMe",
"summary": "Returns the logged user data",
"parameters": [],
"responses": {
"200": {
"description": "Logged user info",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
}
}
}
}
}
}
É só um "pouquinho" maior que o schema do GraphQL, porém ela te permite documentar mais algumas coisas, como por exemplo os tipos de autenticações disponíveis na sua API.