$ git diff
src/app/page.tsx
src/components/about.tsx
$ git addsrc/app/page.tsx $
$ git commit -m'feat: add about page'
$ git push
$ git diff
src/app/page.tsx
src/components/about.tsx
$ git addsrc/app/page.tsx $
$ git commit -m'feat: add about page'
$ git push
Este projeto é a implementação de um backend para uma aplicação de pagamentos, inspirado em um desafio técnico da PicPay. A API foi construída utilizando TypeScript, Node.js e Express, com o objetivo de criar um sistema robusto e escalável para gerenciar usuários, carteiras e transações.
A base do projeto é uma API RESTful, que segue os padrões de mercado para a comunicação entre cliente e servidor. A escolha do Express.js como framework web simplifica a criação e o gerenciamento das rotas, middlewares e controllers.
O README.md do projeto define uma série de endpoints claros e bem definidos para cada recurso (Users, Transactions, Wallets), o que é um pilar do design RESTful.
Endpoints de Transações:
- GET /transactions
- POST /transactions
- GET /transactions/:id
- ... e outros
Uma estrutura de controller para lidar com essas requisições seria responsável por receber os dados, invocar os serviços da aplicação e retornar uma resposta adequada.
Exemplo de um TransactionController:
Este trecho de código é um exemplo de como o controller poderia ser implementado para orquestrar a criação de uma nova transação.
// Exemplo ilustrativo baseado na descrição do projeto
import { Request, Response } from "express";
import { TransactionService } from "../services/TransactionService";
class TransactionController {
async create(req: Request, res: Response) {
const { payerId, payeeId, value } = req.body;
// A lógica de negócio é delegada para a camada de serviço
const transactionService = new TransactionService();
try {
const newTransaction = await transactionService.execute({
payerId,
payeeId,
value,
});
return res.status(201).json(newTransaction);
} catch (error) {
// Erros lançados pelo serviço são capturados e retornados
return res.status(400).json({ message: error.message });
}
}
}
Para a comunicação com o banco de dados PostgreSQL, o projeto utiliza o Prisma, um ORM moderno para Node.js e TypeScript. O Prisma facilita a criação de queries, migrações e, principalmente, garante a tipagem segura entre o banco de dados e o código da aplicação.
O README.md menciona o comando npx prisma migrate dev, indicando o uso do sistema de migrações do Prisma para gerenciar a evolução do schema do banco de dados de forma controlada e versionada.
A definição dos modelos de dados é centralizada em um único arquivo, o schema.prisma.
Exemplo de um schema.prisma:
Este seria um exemplo do schema para definir as tabelas de User, Wallet e Transaction, com seus respectivos relacionamentos.
// Exemplo ilustrativo de um schema.prisma
model User {
id String @id @default(uuid())
fullName String
document String @unique // CPF/CNPJ
email String @unique
password String
sentTransactions Transaction[] @relation("Payer")
receivedTransactions Transaction[] @relation("Payee")
wallet Wallet?
}
model Wallet {
id String @id @default(uuid())
balance Float
userId String @unique
user User @relation(fields: [userId], references: [id])
}
model Transaction {
id String @id @default(uuid())
value Float
payerId String
payeeId String
payer User @relation("Payer", fields: [payerId], references: [id])
payee User @relation("Payee", fields: [payeeId], references: [id])
createdAt DateTime @default(now())
}
Um requisito crucial do desafio é a comunicação com serviços externos para autorizar transações e notificar usuários. Uma boa arquitetura isola essas comunicações em módulos ou classes de serviço específicas.
Isso desacopla a lógica de negócio principal da implementação específica de um cliente HTTP, tornando o sistema mais testável e flexível para trocar o provedor do serviço no futuro.
Exemplo de um AuthorizationService:
Este serviço encapsularia a lógica de chamar o endpoint de autorização externo e retornar uma resposta simples (true ou false).
// Exemplo ilustrativo de um serviço de autorização
import axios from "axios";
class AuthorizationService {
private AUTH_API_URL =
"https://run.mocky.io/v3/5794d450-d2e2-4412-8131-73d0293ac1cc"; // Endpoint mock
async isAuthorized(): Promise<boolean> {
try {
const response = await axios.get(this.AUTH_API_URL);
// A resposta do mock deve ser "Autorizado" para ser válida
return response.data.message === "Autorizado";
} catch (error) {
// Se o serviço externo falhar, a transação não é autorizada
console.error("Authorization service failed:", error);
return false;
}
}
}