# 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 `. **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 ```