📌
Construída com Fastify, Prisma, TypeScript, e Zod para validação de esquemas. Este projeto segue padrões modernos de desenvolvimento como Dependency Injection, Repository Pattern, e inclui documentação automática com Swagger. .
- Tecnologias
- Instalação
- Docker
- Qualidade de Código
- Configuração
- Estrutura do Projeto
- Scripts Disponíveis
- Desenvolvimento
- Documentação da API
- Contribuindo
- Fastify: Framework web rápido e eficiente
- Prisma: ORM moderno para acesso ao banco de dados
- TypeScript: Superset tipado de JavaScript
- Zod: Validação de esquemas com tipagem TypeScript
- JWT: Autenticação baseada em tokens
- Husky: Hooks Git para automação
- Commitizen: Padronização de commits
- Jest: Framework de testes
- Swagger: Documentação automática da API
- Clone o repositório:
git clone https://github.com/seunome/ApifyCloneV2.git
cd ApifyCloneV2/backend
⚠️ Importante: Este projeto funcionará melhor comYARN
para rodar os scripts automáticos de padronização de commit, padronização de código e formatação.
Para instalar o YARN execute no seu terminal o comando abaixo
npm install yarn -g
- Instale as dependências:
yarn install # ou apenas yarn
- Configure o Husky (importante!):
yarn prepare
⚠️ Importante: O comandoprepare
configura o Husky, que gerencia os hooks Git para garantir qualidade do código e padronização de commits.
- Configure o arquivo
.env
na raiz do projeto: Renomeie o arquivo .env.example para .env e configure de acordo com suas informações
DATABASE_URL="file:./backendApiFy.db"
JWT_SECRET="sua_chave_jwt_secreta_aqui"
- Execute as migrações do banco de dados:
yarn db:migrate
- Gere o cliente Prisma:
yarn run db:generate
Se desejar usar docker, execute o comando abaixo na raiz do projeto.
docker compose up -d
Para garantir que seu código e mensagens de commit sempre seguirão o padrão do projeto, use sempre o comando abaixo quando for commitar alterações, caso contrário será retornado um erro.
yarn commit
O projeto está configurado para usar SQLite por padrão, mas você pode mudar para PostgreSQL ou qualquer outro banco suportado pelo Prisma alterando o provider no arquivo prisma/schema.prisma
.
datasource db {
provider = "postgresql" // Altere de "sqlite" para "postgresql"
url = env("DATABASE_URL")
}
Em seguida, atualize sua variável de ambiente DATABASE_URL
no arquivo .env
:
DATABASE_URL="postgresql://user:password@localhost:5432/mydatabase"
src/
├── config/ # Configurações do projeto
├── middlewares/ # Middlewares como autenticação
├── repositories/ # Camada de acesso a dados
├── routes/ # Definição de rotas da API
├── services/ # Lógica de negócios
├── utils/ # Funções utilitárias
├── schemas.ts # Schemas Zod para validação
├── server.ts # Ponto de entrada do servidor
└── types.ts # Tipos TypeScript
npm run dev
: Inicia o servidor de desenvolvimentonpm run db:migrate
: Executa migrações do Prismanpm run db:studio
: Abre o Prisma Studio para visualizar o banco de dadosnpm run db:generate
: Gera o cliente Prismanpm run test
: Executa os testesnpm run prepare
: Configura o Huskynpm run check
: Executa o ESLint para verificar o códigonpm run check:fix
: Corrige automaticamente problemas de lintingnpm run prettier
: Formata o código com Prettiernpm run commit
: Adiciona e comita alterações
- Crie um novo arquivo em
src/routes/
para o recurso (ex:productRoutes.ts
):
// filepath: src/routes/productRoutes.ts
import { FastifyTypedInstance } from '../types';
import { ProductService } from '../services/productService';
import { authenticate } from '../middlewares/authenticate';
export async function productRoutes(fastify: FastifyTypedInstance) {
const productService = new ProductService();
// Rota pública
fastify.get(
'/products',
{
schema: {
description: 'List all products',
tags: ['products'],
response: {
200: /* seu schema Zod aqui */
}
}
},
async (request, reply) => {
const products = await productService.getAllProducts();
return reply.send(products);
}
);
// Rota protegida
fastify.post(
'/products',
{
schema: {
description: 'Create a new product',
tags: ['products'],
security: [{ bearerAuth: [] }], // Indica que requer autenticação
body: /* seu schema Zod aqui */,
response: {
201: /* seu schema Zod aqui */
}
},
preHandler: authenticate, // Middleware de autenticação
},
async (request, reply) => {
// Implementação da rota
}
);
}
- Registre as novas rotas em
src/routes/index.ts
:
// filepath: src/routes/index.ts
import { FastifyTypedInstance } from '../types';
import { userRoutes } from './userRoutes';
import { productRoutes } from './productRoutes';
export async function routes(fastify: FastifyTypedInstance) {
await userRoutes(fastify);
await productRoutes(fastify);
}
- Edite o arquivo
prisma/schema.prisma
para adicionar seu novo modelo:
// filepath: prisma/schema.prisma
model Product {
id String @id @default(uuid())
name String
description String
price Float
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
userId String
user User @relation(fields: [userId], references: [id])
}
- Atualize o modelo
User
para incluir o relacionamento:
// filepath: prisma/schema.prisma
model User {
id String @id @default(uuid())
name String
email String @unique
password String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
products Product[]
}
- Execute o comando de migração:
yarn db:migrate
- Crie um repositório para o novo modelo:
// filepath: src/repositories/productRepository.ts
import { PrismaClient, Product } from '@prisma/client';
const prisma = new PrismaClient();
export interface CreateProductData {
name: string;
description: string;
price: number;
userId: string;
}
export class ProductRepository {
async findAll(): Promise<Product[]> {
return prisma.product.findMany();
}
async create(data: CreateProductData): Promise<Product> {
return prisma.product.create({
data,
});
}
async findById(id: string): Promise<Product | null> {
return prisma.product.findUnique({
where: { id },
});
}
async findByUser(userId: string): Promise<Product[]> {
return prisma.product.findMany({
where: { userId },
});
}
}
O Prisma suporta vários tipos de relacionamentos:
- Um para Um (1:1):
// filepath: prisma/schema.prisma
model User {
id String @id @default(uuid())
profile Profile?
}
model Profile {
id String @id @default(uuid())
bio String
userId String @unique
user User @relation(fields: [userId], references: [id])
}
- Um para Muitos (1:N):
// filepath: prisma/schema.prisma
model User {
id String @id @default(uuid())
posts Post[]
}
model Post {
id String @id @default(uuid())
title String
content String
userId String
user User @relation(fields: [userId], references: [id])
}
- Muitos para Muitos (N:M):
// filepath: prisma/schema.prisma
model Post {
id String @id @default(uuid())
title String
categories Category[] @relation("PostToCategory")
}
model Category {
id String @id @default(uuid())
name String
posts Post[] @relation("PostToCategory")
}
A documentação da API é gerada automaticamente usando Swagger. Após iniciar o servidor, acesse:
http://localhost:3333/docs
A interface do Swagger mostrará todas as rotas disponíveis, seus parâmetros, corpo de requisição e respostas.
- Faça o fork do projeto
- Crie sua feature branch (
git checkout -b feature/minha-feature
) - Execute
yarn prepare
para configurar o Husky - Faça suas alterações
- Execute os testes (
yarn test
) - Use
yarn commit
para fazer commits padronizados - Envie para o branch (
git push origin feature/minha-feature
) - Abra um Pull Request
Desenvolvido por Daniel Alencar