320 lines
No EOL
5.9 KiB
Markdown
320 lines
No EOL
5.9 KiB
Markdown
# Toptran
|
|
|
|
Aplicação full-stack composta por um backend REST em Node.js/Express com autenticação JWT e um aplicativo mobile em React Native/Expo.
|
|
|
|
---
|
|
|
|
## Estrutura do projeto
|
|
|
|
```
|
|
toptran/
|
|
├── backend/ → API REST (Node.js, Express, Prisma, PostgreSQL)
|
|
└── mobile/ → App mobile (React Native, Expo)
|
|
```
|
|
|
|
---
|
|
|
|
## Backend
|
|
|
|
### Tecnologias
|
|
|
|
| Pacote | Versão | Função |
|
|
|---|---|---|
|
|
| Node.js | LTS | Runtime |
|
|
| Express | 5 | Framework HTTP |
|
|
| TypeScript | 5 | Tipagem |
|
|
| Prisma | 7 | ORM |
|
|
| PostgreSQL | — | Banco de dados |
|
|
| bcryptjs | — | Hash de senha |
|
|
| jsonwebtoken | — | Access token (JWT) |
|
|
| zod | — | Validação de input |
|
|
| @prisma/adapter-pg | — | Driver nativo do Prisma 7 |
|
|
|
|
### Arquitetura em camadas
|
|
|
|
```
|
|
src/
|
|
├── server.ts → Inicialização do Express e registro das rotas
|
|
├── lib/
|
|
│ └── prisma.ts → Singleton do PrismaClient com adapter PG
|
|
├── repositories/
|
|
│ ├── users.repository.ts → Queries de usuários no Prisma
|
|
│ └── tokens.repository.ts → Queries de tokens no Prisma
|
|
├── services/
|
|
│ ├── auth.service.ts → Lógica de registro, login, logout e JWT
|
|
│ └── users.service.ts → Lógica de leitura, atualização e remoção de usuários
|
|
├── controllers/
|
|
│ ├── auth.controller.ts → Recebe requests e chama auth.service
|
|
│ └── users.controller.ts → Recebe requests e chama users.service
|
|
├── middlewares/
|
|
│ └── auth.middleware.ts → Valida o Bearer token nas rotas protegidas
|
|
└── routes/
|
|
├── auth.routes.ts → Rotas públicas de autenticação
|
|
└── users.routes.ts → Rotas protegidas de usuário
|
|
```
|
|
|
|
**Fluxo de uma requisição:**
|
|
|
|
```
|
|
Request → routes → middleware (se protegida) → controller → service → repository → Prisma → PostgreSQL
|
|
```
|
|
|
|
### Modelos do banco de dados
|
|
|
|
```prisma
|
|
model users {
|
|
id String @id
|
|
name String
|
|
email String @unique
|
|
password String
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime
|
|
tokens tokens[]
|
|
}
|
|
|
|
model tokens {
|
|
id String @id
|
|
token String @unique
|
|
type TokenType
|
|
userId String
|
|
expiresAt DateTime
|
|
createdAt DateTime @default(now())
|
|
users users @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
enum TokenType {
|
|
REFRESH
|
|
}
|
|
```
|
|
|
|
### Variáveis de ambiente
|
|
|
|
Crie o arquivo `backend/.env` com as variáveis abaixo:
|
|
|
|
```env
|
|
DB_USER=postgres
|
|
DB_PASSWORD=postgres
|
|
DB_HOST=localhost
|
|
DB_PORT=5432
|
|
DB_NAME=toptran
|
|
|
|
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/toptran"
|
|
|
|
PORT=4000
|
|
JWT_SECRET=sua_chave_secreta_aqui
|
|
```
|
|
|
|
> `JWT_SECRET` é obrigatório em produção. O access token expira em **15 minutos** e o refresh token em **7 dias**.
|
|
|
|
### Instalação e execução
|
|
|
|
```bash
|
|
cd backend
|
|
|
|
# Instalar dependências
|
|
npm install
|
|
|
|
# Gerar cliente Prisma
|
|
npx prisma generate
|
|
|
|
# Rodar migrations
|
|
npx prisma migrate deploy
|
|
|
|
# Iniciar em modo desenvolvimento
|
|
npm run dev
|
|
|
|
# Build de produção
|
|
npm run build
|
|
npm start
|
|
```
|
|
|
|
### API Reference
|
|
|
|
#### Autenticação — `/auth`
|
|
|
|
> Rotas públicas, não requerem token.
|
|
|
|
**POST `/auth/register`**
|
|
|
|
Cria uma nova conta de usuário.
|
|
|
|
```json
|
|
// Request body
|
|
{
|
|
"name": "João Silva",
|
|
"email": "joao@email.com",
|
|
"password": "minhasenha"
|
|
}
|
|
|
|
// Response 201
|
|
{
|
|
"id": "uuid",
|
|
"name": "João Silva",
|
|
"email": "joao@email.com"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
**POST `/auth/login`**
|
|
|
|
Autentica o usuário e retorna os tokens.
|
|
|
|
```json
|
|
// Request body
|
|
{
|
|
"email": "joao@email.com",
|
|
"password": "minhasenha"
|
|
}
|
|
|
|
// Response 200
|
|
{
|
|
"accessToken": "eyJ...",
|
|
"refreshToken": "uuid"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
**POST `/auth/logout`**
|
|
|
|
Revoga o refresh token.
|
|
|
|
```json
|
|
// Request body
|
|
{
|
|
"refreshToken": "uuid"
|
|
}
|
|
|
|
// Response 204 (sem body)
|
|
```
|
|
|
|
---
|
|
|
|
#### Usuários — `/users`
|
|
|
|
> Rotas protegidas. Enviar o header `Authorization: Bearer <accessToken>`.
|
|
|
|
**GET `/users/me`**
|
|
|
|
Retorna os dados do usuário autenticado.
|
|
|
|
```json
|
|
// Response 200
|
|
{
|
|
"id": "uuid",
|
|
"name": "João Silva",
|
|
"email": "joao@email.com",
|
|
"createdAt": "2026-04-27T00:00:00.000Z"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
**PUT `/users/me`**
|
|
|
|
Atualiza nome, e-mail e/ou senha. Todos os campos são opcionais.
|
|
|
|
```json
|
|
// Request body
|
|
{
|
|
"name": "João Atualizado",
|
|
"email": "novo@email.com",
|
|
"password": "novasenha"
|
|
}
|
|
|
|
// Response 200
|
|
{
|
|
"id": "uuid",
|
|
"name": "João Atualizado",
|
|
"email": "novo@email.com"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
**DELETE `/users/me`**
|
|
|
|
Remove a conta do usuário autenticado.
|
|
|
|
```
|
|
// Response 204 (sem body)
|
|
```
|
|
|
|
---
|
|
|
|
#### Respostas de erro
|
|
|
|
| Status | Situação |
|
|
|---|---|
|
|
| 400 | Input inválido (falha na validação Zod) |
|
|
| 401 | Token ausente, inválido ou expirado |
|
|
| 404 | Recurso não encontrado |
|
|
| 409 | E-mail já cadastrado |
|
|
|
|
---
|
|
|
|
### Deploy com Docker / Podman
|
|
|
|
```bash
|
|
cd backend
|
|
|
|
# Build da imagem
|
|
podman build -t top-tran-backend .
|
|
|
|
# Subir com compose
|
|
podman-compose up -d
|
|
```
|
|
|
|
O container expõe a porta `3000` e o serviço é reiniciado automaticamente em caso de falha.
|
|
|
|
---
|
|
|
|
## Mobile
|
|
|
|
### Tecnologias
|
|
|
|
| Pacote | Versão | Função |
|
|
|---|---|---|
|
|
| React Native | 0.81.5 | Framework mobile |
|
|
| Expo | 54 | Plataforma e toolchain |
|
|
| Expo Router | 6 | Navegação baseada em arquivos |
|
|
| Axios | 1 | Cliente HTTP |
|
|
| TypeScript | 5 | Tipagem |
|
|
|
|
### Telas
|
|
|
|
| Arquivo | Rota | Descrição |
|
|
|---|---|---|
|
|
| `src/app/index.tsx` | `/` | Tela de login |
|
|
| `src/app/signup.tsx` | `/signup` | Tela de cadastro |
|
|
|
|
### Execução
|
|
|
|
```bash
|
|
cd mobile
|
|
|
|
# Instalar dependências
|
|
npm install
|
|
|
|
# Iniciar o servidor Expo
|
|
npm start
|
|
|
|
# Abrir no Android
|
|
npm run android
|
|
|
|
# Abrir no iOS
|
|
npm run ios
|
|
```
|
|
|
|
### Conectar ao dispositivo Android via AVD na VM
|
|
|
|
1. Ligue o dispositivo Android (AVD)
|
|
2. No terminal local, crie o túnel SSH reverso:
|
|
```bash
|
|
ssh -R 5555:localhost:5555 dev@175.15.15.93
|
|
```
|
|
3. Conecte o ADB ao dispositivo tunelado:
|
|
```bash
|
|
adb connect localhost:5555
|
|
``` |