Os helpers são funções ou classes que fornecem funcionalidades comuns que podem ser reutilizadas em várias partes da aplicação. Eles ajudam a reduzir a duplicação de código e simplificar tarefas recorrentes.
Vamos adicionar uma nova pasta helpers
ao projeto, onde colocaremos funções auxiliares que podem ser utilizadas por qualquer camada.
src/
│
├── config/
│ └── database.ts
│
├── controllers/
│ └── userController.ts
│
├── helpers/
│ └── validationHelper.ts
│
├── models/
│ └── userModel.ts
│
├── repositories/
│ └── userRepository.ts
│
├── routes/
│ └── userRoutes.ts
│
├── migrations/
│ └── migrations.ts
│
├── server.ts
helpers/validationHelper.ts
Um exemplo de helper pode ser a função de validação de e-mail, que será usada para garantir que os e-mails fornecidos pelos usuários sejam válidos.
export const isValidEmail = (email: string): boolean => {
const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
return emailRegex.test(email);
};
Agora, no userController, vamos utilizar o helper isValidEmail
para validar os e-mails antes de adicionar um novo usuário.
import { Request, Response } from 'express';
import { UserRepository } from '../repositories/userRepository';
import { isValidEmail } from '../helpers/validationHelper';
const userRepository = new UserRepository();
export const getUsers = async (req: Request, res: Response) => {
try {
const users = await userRepository.getAllUsers();
res.status(200).json(users);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Erro ao buscar usuários' });
}
};
export const addUser = async (req: Request, res: Response) => {
const { name, email } = req.body;
// Validando o e-mail com o helper
if (!isValidEmail(email)) {
return res.status(400).json({ error: 'Email inválido' });
}
try {
const user = await userRepository.addUser(name, email);
res.status(201).json(user);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Erro ao adicionar usuário' });
}
};
As camadas auxiliares, como services ou use cases, podem ser utilizadas para encapsular a lógica de negócios e permitir que os controllers permaneçam enxutos e focados em lidar com as requisições.
services/userService.ts
Vamos adicionar um serviço para encapsular a lógica de negócios relacionada aos usuários. Esse serviço vai lidar com a validação e chamar o repositório para manipular os dados.
import { UserRepository } from '../repositories/userRepository';
import { isValidEmail } from '../helpers/validationHelper';
export class UserService {
private userRepository: UserRepository;
constructor() {
this.userRepository = new UserRepository();
}
async createUser(name: string, email: string) {
if (!isValidEmail(email)) {
throw new Error('Email inválido');
}
return await this.userRepository.addUser(name, email);
}
async listUsers() {
return await this.userRepository.getAllUsers();
}
}
Agora, o controller vai delegar as responsabilidades ao UserService:
import { Request, Response } from 'express';
import { UserService } from '../services/userService';
const userService = new UserService();
export const getUsers = async (req: Request, res: Response) => {
try {
const users = await userService.listUsers();
res.status(200).json(users);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Erro ao buscar usuários' });
}
};
export const addUser = async (req: Request, res: Response) => {
const { name, email } = req.body;
try {
const user = await userService.createUser(name, email);
res.status(201).json(user);
} catch (err) {
res.status(400).json({ error: err.message });
}
};