Skip to content

Quotes API using TypeScript, NodeJS and Express.

Notifications You must be signed in to change notification settings

jsericksk/Quotes-Api

Repository files navigation

Quotes API

tech-info

Objetivo

Esse é um projeto básico criado com o objetivo de aprender mais sobre APIs/backend, assim como TypeScript e NodeJS. É um projeto com fins unicamente de estudos.

✏️ Funcionalidades

A API tem como principal função publicar e obter frases, sendo necessário se registrar para tal. Possui um CRUD completo de frases para usuários logados, com opções de adicionar, obter, atualizar e excluir frases, além de contar com o recurso de paginação ao obter as frases. Os dados são armazenados em um banco de dados PostegreSQL.

🛠️ Principais tecnologias e bibliotecas utilizadas

🚀 Executar localmente

Estou utilizando o yarn, mas você pode utilizar o gerenciador de pacotes de sua preferência. Antes de executar localmente, é necessário definir as variáveis de ambiente no arquivo .env. Você precisa criar o arquivo .env e copiar as variáveis do .env.example, preenchendo com os valores de configuração adequados.

IMPORTANTE: ACCESS_TOKEN_SECRET_KEY e REFRESH_TOKEN_SECRET_KEY devem ter valores diferentes, caso contrário, um refresh token poderá ser usado como access token.

  • yarn dev: Executar localmente.
  • yarn test ou yarn jest: Rodar todos os testes.
  • yarn knex:migrate: Executar migrations.
  • yarn knex:rollback: Executar rollback.
  • yarn knex:seed: Executar seeds.

📝 API Docs

Rotas /auth:

Rotas /quotes:

Manipulação de erros:

Registrar usuário

POST /auth/register

  • Request - Body:
{
  "email": "Email do usuário",
  "username": "Nome do usuário. Deve conter no mínimo 3 caracteres e no máximo 50",
  "password": "Senha do usuário. Deve conter no mínimo 6 caracteres"
}
  • Response - Status 201: ID do usuário registrado (int).

Login

POST /auth/login

  • Request - Body:
{
  "email": "Email do usuário",
  "password": "Senha do usuário. Deve conter no mínimo 6 caracteres"
}
  • Response - Status 200:
{
  "accessToken": "Access token válido por 1h",
  "refreshToken": "Refresh token válido por 7 dias (ou até ser utilizado para gerar um novo access token)"
}

Refresh token

POST /auth/refresh-token

  • Request - Body:
{
  "refreshToken": "Refresh token válido no formato JWT gerado durante o login"
}
  • Response - Status 200:
{
  "accessToken": "Novo access token válido por 1h",
  "refreshToken": "Novo refresh token válido por 7 dias (ou até ser utilizado para gerar um novo access token)"
}

Obter todas as frases

NOTA IMPORTANTE: Todas as rotas de frases são protegidas e precisam de um Authorization Header.
Passe Authorization: Bearer access token no header de requisição.

  • Você pode pesquisar por frases ao fornecer um filter e obter todas as frases de um determinado usuário ao fornecer o userId.

GET /quotes

GET /quotes?page=1

GET /quotes?filter=conhecimento

GET /quotes?userId=1

GET /quotes?page=1&filter=conhecimento

GET /quotes?userId=1&filter=conhecimento

  • Response - Status 200:
{
  "info": {
    "count": 20,
    "pages": 2,
    "next": "/quotes?page=2",
    "previous": null
  },
  "results": [
    {
      "id": 1,
      "quote": "A imaginação é mais importante que o conhecimento.",
      "author": "Albert Einstein",
      "postedByUsername": "John",
      "postedByUserId": 1,
      "publicationDate": "2023-06-21T15:20:28.936Z"
    },
    [...]
  ]
}
  • count: Número total de frases.
  • pages: Número total de páginas disponíveis.
  • next: Próxima página. null se não houver nenhuma.
  • previous: Página anterior. null se não houver nenhuma.
  • results: Frases encontradas.
  • O limite de frases por página é 15.

Obter frase por id

GET /quotes/:id

  • Response - Status 200:
{
  "id": 1,
  "quote": "A imaginação é mais importante que o conhecimento.",
  "author": "Albert Einstein",
  "postedByUsername": "John",
  "postedByUserId": 1,
  "publicationDate": "2023-06-21T15:20:28.936Z"
}

Publicar frase

POST /quotes

  • Request - Body:
{
  "quote": "Frase. Deve conter no mínimo 7 caracteres e no máximo 1000",
  "author": "Nome do autor. Deve conter no mínimo 1 caractere e no máximo 80"
}
  • Response - Status 201:
{
  "id": 1,
  "quote": "A imaginação é mais importante que o conhecimento.",
  "author": "Albert Einstein",
  "postedByUsername": "John",
  "postedByUserId": 1,
  "publicationDate": "2023-06-21T15:20:28.936Z"
}

Atualizar frase

PUT /quotes/:id

  • Request - Body:
{
  "quote": "Frase atualizada. Deve conter no mínimo 7 caracteres e no máximo 1000",
  "author": "Nome do autor atualizado. Deve conter no mínimo 1 caractere e no máximo 80"
}
  • Response - Status 204: Não há body de resposta.

Excluir frase

DELETE /quotes/:id

  • Response - Status 204: Não há body de resposta.

Error handling

Todos os endpoints que precisam de um body/params/query podem retornar uma BAD_REQUEST (400) se a requisição contiver valores inválidos. Exemplos de erros:

  • Login:
{
  "errors": {
    "body": {
      "email": "Invalid email",
      "password": "String must contain at least 6 character(s)"
    }
  }
}
  • Tentar obter todas as frases com ?page=abc:
{
  "errors": {
    "query": {
      "page": "Expected number, received nan"
    }
  }
}
  • Atualizar frase com campos no body e id inválidos:
{
  "errors": {
    "body": {
      "quote": "String must contain at least 7 character(s)",
      "author": "String must contain at least 1 character(s)"
    },
    "params": {
      "id": "Expected number, received nan"
    }
  }
}

Todos os endpoints podem retornar um body contendo um error e error_code padrão. error_code sempre será retornado com um valor "unespecifed" caso não seja importante distinguir o tipo de erro. Códigos de erro disponíveis:

  • email_already_exists: Quando tentar se registrar com e-mail que já existe.
  • username_already_exists: Quando tentar se registrar com nome de usuário que já existe.
  • search_without_results: Quando nenhuma frase com o "filter" aplicado for encontrada.
  • user_without_posts: Quando o usuário não possuir nenhuma frase publicada.
  • invalid_page: Quando uma página inválida for informada na paginação.
{
  "error": "Email not available",
  "error_code": "email_not_available"
}

Alguns endpoints podem retornar NOT_FOUND (404) se o recurso não for encontrado ou a frase não pertencer ao usuário.

  • Tentar atualizar ou excluir com o id de uma frase que não existe ou não pertence ao usuário:
{
  "error": "There is no quote with the given id",
  "error_code": "unspecified"
}
  • Tentar obter frases com uma page maior do que a quantidade de páginas disponíveis:
{
  "error": "Invalid page, no more items",
  "error_code": "invalid_page"
}

Releases

No releases published

Packages

No packages published