Há alguns dias você recebeu uma demanda para elaborar a API de um serviço de locação de filmes. Porém a forma com que você executou e as ferramentas que utilizou não agradaram o nosso cliente... É... ele é exigente.
Portanto, agora você precisará reescrever esse projeto com outras tecnologias. Além disso o cliente adicionou algumas novas regras de negócio ao projeto.
Bora para esse desafio?!
A entrega deve seguir as seguintes regras:
- O código deve estar em TypeScript, caso não esteja a entrega será zerada;
- Deve ser feita a serialização dos dados utilizando a biblioteca zod.
- Deverá ser utilizado um banco de dados postgres para a elaboração da API;
- Deverá utilizar TypeORM no lugar de PG e PG-Format
- O nome da tabela/entidade, colunas e demais especificações, devem ser seguidas à risca. Caso tenha divergência, os testes não funcionarão e será descontado nota;
- Tenha muita atenção sobre o nome das chaves nos objetos de entrada e saída de cada requisição;
- Na raiz do diretório deve-se conter uma imagem do DER nomeada como diagram.png/jpg
- Esse DER não pode ser o criado pelo dbeaver.
Essa entrega possui testes automatizados, portanto:
-
A alteração nos testes implica em ter a nota da entrega zerada.
-
Os arquivos de testes e configuração para execução deles já se encontram no repositório da entrega, sendo necessário configurar a conexão com o banco de dados para teste e desenvolvimento, e todo o restante para que a aplicação funcione.
-
Não altere nenhum arquivo, apenas acrescente os arquivos que forem necessários.
Dica! Como essa entrega contém testes, sempre que criar uma nova rota execute o comando de execução dos testes npm run test ou yarn test a depender do gerenciador de pacotes usado. A execução dos testes a cada criação de rota ajuda no debug e no andamento do projeto, e evita erros surpresas quando o projeto estiver 100% concluído. Também use o insomnia para ir testando as rotas na medida que for desenvolvendo o projeto.
Inicialização do projeto
-
Será necessário estruturar todo o repositório e instalar as dependências corretas para o funcionamento do projeto.
-
No diretório estão apenas os arquivos e sub-pastas:
-
.env.example:
- Contendo apenas a variável DATABASE_URL que deverá conter a url de conexão com o banco;
- Deve ser utilizado como base para o seu .env.
-
package.json:
- Estão definidas nesse arquivos apenas as bibliotecas relacionadas aos testes;
- Todas as demais bibliotecas devem ser instaladas por você.
-
.gitignore:
- Caso sinta necessidade pode adicionar novos arquivos à serem ignorados.
-
jest.config.ts:
- Arquivo de configuração para os testes.
-
src/entities:
- Por necessidade dos testes, precisamos que a estrutura siga a pré definida.
- Será necessário completar o arquivo movies.entity.ts com a criação correta da entidade de Movies.
- Apenas acrescente o código necessário, não mude nada que já está feito.
-
src/__tests__:
-
Não devem ser alterados, caso os testes tenham qualquer tipo de alteração a entrega será zerada.
Atenção! Nessa entrega a conexão com o banco de dados não está sendo realizada. Portanto lembre-se de realizar a conexão para o banco de desenvolvimento e para o banco de testes.
-
-
Método | Endpoint | Responsabilidade |
---|---|---|
POST | /movies | Cadastra um novo filme |
GET | /movies | Lista todos os filmes cadastrados |
PATCH | /movies/:id | Atualiza o filme passado por id |
DELETE | /movies/:id | Deleta o filme passado por id |
-
Deve ser criado um banco de dados em PostgreSQL com uma tabela/entidade nomeada como movies, para armazenar os dados das requisições.
-
A tabela de movies deve ter as colunas necessárias para armazenar os seguintes dados:
- id: inteiro, sequencial e chave primária.
- name: string, tamanho máximo de 50, único e obrigatório.
- description: texto.
- duration: inteiro e obrigatório.
- price: inteiro e obrigatório.
-
Como estamos trabalhando com TypeORM, deve ser criada uma entidade de movies com os campos descritos acima, e essa entidade vai ser convertida em tabela através de uma migração.
-
O nome da classe da entidade deve ser Movie e deve ser criado um arquivo index.ts dentro da pasta de entities centralizando o export dela para que os testes funcionem.
-
Nas rotas POST e PATCH, é necessário serializar os dados de entrada utilizando o zod. Chaves não mapeadas devem ser ignoradas.
-
Na rota POST /movies, a chave id deve ser ignorada, o próprio serviço deve preencher esse dado. A chave description é opcional, caso não seja enviada deve ser salvo como null.
-
Na rota PATCH /movies/:id, a chave id não pode ser atualizada, caso enviada no body deve ser ignorada.
A rota GET /movies deve conter paginação.
- Essa rota recebe quatro query params, sendo eles: page, perPage, order e sort.
- Essa rota retornará um objeto de paginação que irá conter as seguintes chaves: prevPage, nextPage, count e data.
Segue abaixo o que cada chave significa e a regra de cada um dos query params.
-
sort: recebe em qual coluna a ordenação deve ser feita. Pode receber apenas dois valores:
- price
- duration
- Caso nenhum desses valores seja enviado, deve ordenar por id.
-
order: recebe qual o tipo de ordenação que será feita. Pode receber apenas dois valores:
- asc
- desc
- Caso nenhum desses valores seja enviado, deve utilizar asc.
-
perPage: recebe qual a quantidade de dados que devem ser retornados.
- Deve receber um número inteiro maior que 0 e menor ou igual a 5
- Caso o número enviado não atenda esse requisito, deve retornar cinco dados.
- Deve receber um número inteiro maior que 0 e menor ou igual a 5
-
page: recebe qual página deve ser retornada.
- Recebe apenas números inteiros e maiores que 0
- Caso o número enviado não atenda esses requisitos, deve utilizar a primeira página, ou seja, deve ser 1
- Deve respeitar o perPage:
- se page for igual à três e perPage for igual à dois, deve retornar dois dados, começando pelo id cinco e indo até o id seis.
Deve seguir as regras do page e do perPage.
Um exemplo mais claro estará nos exemplos de requisição da rota GET - /movies
- prevPage: página anterior
- tipo: string ou null;
- Caso a próxima página exista, deve retornar uma url redirecionando para a página;
- Caso contrario deve retornar null;
- nextPage: próxima página;
- tipo: string ou null;
- Caso a próxima página exista, deve retornar uma url redirecionando para a página;
- Caso contrario deve retornar null;
- count: contagem de dados existentes no banco de dados;
- tipo: number;
- data: os filmes listados pela requisição;
- tipo: Array de movies;
- A quantidade de filmes retornados deve seguir as regras do perPage.
Todos os casos de erros listados a seguir, devem ser executados por meio de middlewares.
-
O nome (name) deve ser único. Nas rotas POST e PATCH /movies, caso seja enviado um nome já registrado, deve retornar a mensagem de erro e o status code mencionados abaixo.
Resposta do servidor: Body: Formato Json Status code: 409 CONFLICT { "message": "Movie already exists." }
-
A serialização dos dados de entrada deve ser feita utilizando o zod. Essa serialização deve acontecer nas rotas POST e PATCH. Em caso de erro ao validar os dados, deve retornar a mensagem de erro e o status code mencionados abaixo.
- O retorno dos erros do zod deve estar dentro de um objeto "message"
Resposta do servidor: Body: Formato Json Status code: 400 BAD REQUEST { "message": { "name": ["Expected string, received number"], "duration": ["Expected number, received string"] } }
-
Em todas as rotas que recebem id por parâmetro, deve verificar se o id informado existe. Caso o filme (movie) não exista, deve retornar a mensagem de erro e o status code mencionados abaixo.
Resposta do servidor: Body: Formato Json Status code: 404 NOT FOUND { "message": "Movie not found" }
Rota de criação de filmes. A chave description é opcional.
Dados de Envio: |
---|
Body: Formato Json |
{
"id": 40,
"duration": 60,
"name": "Movie: Sem description",
"price": 200
}
Resposta do servidor: |
---|
Body: Formato Json |
Status code: 201 CREATED |
{
"id": 1,
"name": "Movie: Sem description",
"description": null,
"duration": 60,
"price": 200
}
Deve ser possível listar os filmes armazenados no banco de dados. Seguindo as regras de paginação
Url da requisição: http://localhost:3000/movies/?sort=price&order=desc&page=2&perPage=3
Resposta do servidor: |
---|
Body: Formato Json |
Status code: 200 OK |
{
"prevPage": "http://localhost:3000/movies?page=1&perPage=3",
"nextPage": "http://localhost:3000/movies?page=3&perPage=3",
"count": 14,
"data": [
{
"id": 8,
"name": "Filme 08",
"description": null,
"duration": 88,
"price": 72
},
{
"id": 4,
"name": "Filme 04",
"description": null,
"duration": 75,
"price": 72
},
{
"id": 11,
"name": "Filme 11",
"description": null,
"duration": 7,
"price": 68
}
]
}
Deve ser possível atualizar um filme pelo id recebido nos parâmetros da rota.
Url da requisição: http://localhost:3000/movies/4
Dados de Envio: |
---|
Body: Formato Json |
{
"id": 55,
"duration": 130,
"price": 200
}
Resposta do servidor: |
---|
Body: Formato Json |
Status code: 200 OK |
{
// repare no valor enviado e no recebido do id
"id": 4,
"name": "Filme 04",
"description": null,
"duration": 130,
"price": 200
}
Deve ser possível deletar um filme pelo id recebido nos parâmetros da rota.
Resposta do servidor: |
---|
Body: Nenhum body deve ser retornado |
Status code: 204 NO CONTENT |