Uma API completa para sistema de agendamentos de barbearias desenvolvida com Node.js, TypeScript, Express, PostgreSQL e Prisma.
- Node.js + TypeScript - Runtime e linguagem
- Express.js - Framework web
- PostgreSQL - Banco de dados relacional
- Prisma - ORM moderno
- JWT - Autenticação
- Bcrypt - Hash de senhas
- Docker - Containerização
O projeto segue a arquitetura Model-View-Controller (MVC):
- Models (
src/models/) - Acesso aos dados e lógica de banco - Controllers (
src/controllers/) - Lógica de negócio e validações - Routes (
src/routes/) - Definição de endpoints - Services (
src/services/) - Orquestração de operações complexas - Middleware (
src/middleware/) - Autenticação e autorização
CREATE TABLE usuarios (
id_usuario SERIAL PRIMARY KEY,
nome VARCHAR(255) NOT NULL,
telefone VARCHAR(20) NOT NULL UNIQUE,
email VARCHAR(255) NOT NULL UNIQUE,
senha_hash VARCHAR(255) NOT NULL,
tipo_usuario VARCHAR(20) NOT NULL CHECK (tipo_usuario IN ('cliente', 'barbeiro', 'proprietario')),
data_cadastro TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);CREATE TABLE barbearias (
id_barbearia SERIAL PRIMARY KEY,
id_proprietario INTEGER NOT NULL,
nome VARCHAR(255) NOT NULL,
endereco TEXT NOT NULL,
telefone_contato VARCHAR(20) NOT NULL,
horario_funcionamento TEXT,
data_cadastro TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMPTZ NULL,
CONSTRAINT fk_proprietario FOREIGN KEY(id_proprietario) REFERENCES usuarios(id_usuario)
);CREATE TABLE barbeiros (
id_barbeiro SERIAL PRIMARY KEY,
id_usuario INTEGER NOT NULL UNIQUE,
id_barbearia INTEGER NOT NULL,
especialidades TEXT,
CONSTRAINT fk_usuario FOREIGN KEY(id_usuario) REFERENCES usuarios(id_usuario),
CONSTRAINT fk_barbearia FOREIGN KEY(id_barbearia) REFERENCES barbearias(id_barbearia)
);Cria uma nova barbearia com proprietário em uma única transação.
Request Body:
{
"barbearia_nome": "Barbearia do João",
"endereco": "Rua das Flores, 123",
"telefone_contato": "(11) 99999-9999",
"horario_funcionamento": "Seg-Sex: 8h-18h, Sab: 8h-16h",
"proprietario_nome": "João Silva",
"proprietario_email": "joao@email.com",
"proprietario_telefone": "(11) 88888-8888",
"proprietario_senha": "senha123"
}Response (201):
{
"message": "Barbearia criada com sucesso",
"token": "jwt_token_here",
"proprietario": { /* dados do proprietário */ },
"barbearia": { /* dados da barbearia */ }
}Realiza login de qualquer tipo de usuário.
Request Body:
{
"email": "joao@email.com",
"senha": "senha123"
}Response (200):
{
"message": "Login realizado com sucesso",
"token": "jwt_token_here",
"usuario": {
"id_usuario": 1,
"nome": "João Silva",
"email": "joao@email.com",
"tipo_usuario": "proprietario"
}
}Valida token JWT (requer autenticação).
Headers:
Authorization: Bearer jwt_token_here
Cadastra um novo cliente.
Request Body:
{
"nome": "Maria Santos",
"email": "maria@email.com",
"telefone": "(11) 77777-7777",
"senha": "senha123"
}Busca perfil do cliente autenticado (requer autenticação como cliente).
Lista todas as barbearias ativas (público).
Busca barbearia específica por ID (público).
Lista barbearias do proprietário autenticado (requer autenticação como proprietário).
Atualiza dados da barbearia (requer autenticação como proprietário).
Request Body:
{
"nome": "Novo Nome da Barbearia",
"endereco": "Novo Endereço",
"telefone_contato": "(11) 99999-0000",
"horario_funcionamento": "Seg-Dom: 8h-20h"
}Remove barbearia (soft delete - requer autenticação como proprietário).
Adiciona novo barbeiro à barbearia (requer autenticação como proprietário).
Request Body:
{
"nome": "Carlos Barbeiro",
"email": "carlos@email.com",
"telefone": "(11) 66666-6666",
"senha": "senha123",
"especialidades": "Corte clássico, Barba, Bigode"
}Lista barbeiros da barbearia (requer autenticação como proprietário).
Atualiza especialidades do barbeiro (requer autenticação como proprietário).
Remove barbeiro (requer autenticação como proprietário).
- cliente - Pode agendar serviços
- barbeiro - Pode gerenciar seus atendimentos
- proprietario - Pode gerenciar barbearia e barbeiros
Authorization: Bearer <jwt_token>Controla acesso baseado no tipo de usuário:
requireRole(['proprietario']) // Apenas proprietários
requireRole(['cliente']) // Apenas clientes
requireRole(['barbeiro']) // Apenas barbeiros- Node.js 18+
- PostgreSQL
- Docker (opcional)
git clone <repository-url>
cd hasty-barber
npm installConfigure as variáveis de ambiente no arquivo .env:
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/hasty_barber"
PORT=3000
NODE_ENV=development
JWT_SECRET=hasty_barber_jwt_secret_key_2025_ultra_secure# Iniciar PostgreSQL com Docker
npm run docker:up
# Gerar cliente Prisma
npx prisma generate
# Executar migrações
npx prisma migrate dev
# Criar views, roles, triggers e pgp
npx ts-node prisma/apply-views.ts
# Inserir dados no banco
npx ts-node prisma/seed.ts# Desenvolvimento
npm run dev
# Produção
npm run build
npm startcurl -X POST http://localhost:3000/api/onboarding/barbershop \
-H "Content-Type: application/json" \
-d '{
"barbearia_nome": "Barbearia Teste",
"endereco": "Rua Teste, 123",
"telefone_contato": "(11) 99999-9999",
"proprietario_nome": "João Teste",
"proprietario_email": "joao@teste.com",
"proprietario_telefone": "(11) 88888-8888",
"proprietario_senha": "senha123"
}'curl -X POST http://localhost:3000/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "joao@teste.com",
"senha": "senha123"
}'curl -X POST http://localhost:3000/api/barbearias/barbeiros \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SEU_TOKEN_AQUI" \
-d '{
"nome": "Carlos Barbeiro",
"email": "carlos@teste.com",
"telefone": "(11) 77777-7777",
"senha": "senha123",
"especialidades": "Corte e Barba"
}'- Sistema de agendamentos
- Notificações por email/SMS
- Upload de imagens de perfil
- Sistema de avaliações
- Relatórios financeiros
- API de pagamentos
Este projeto está sob a licença MIT.