📌
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 comYARNpara 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 comandoprepareconfigura o Husky, que gerencia os hooks Git para garantir qualidade do código e padronização de commits.
- Configure o arquivo
.envna 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:generateSe desejar usar docker, execute o comando abaixo na raiz do projeto.
docker compose up -dPara 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 commitO 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.prismapara 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
Userpara 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 preparepara configurar o Husky - Faça suas alterações
- Execute os testes (
yarn test) - Use
yarn commitpara fazer commits padronizados - Envie para o branch (
git push origin feature/minha-feature) - Abra um Pull Request
Desenvolvido por Daniel Alencar
