API Node Desacoplada: Criando os AdaptRouter para o Express e o Fastify

zorasantos

Zoranildo Santos

Posted on August 1, 2023

API Node Desacoplada: Criando os AdaptRouter para o Express e o Fastify

Neste artigo vamos criar os adaptadores de rota para o express e para o fastify. Com isso nossa aplicação finalmente será capaz de funcionar com express ou fastify, apenas alterando o valor da variável SERVER_TYPE no arquivo .env.

Dentro da pasta infra crie uma nova pasta chamada adapter. Dentro da pasta adapter crie dois arquivos adaptRouteFastify.ts e adaptRouteExpress.ts.

Criando o adaptador para o Express

No arquivo adaptRouteExpress.ts insira o código abaixo:

import { Request, Response } from 'express'
import { HttpRequest } from '../shared/protocols/http'
import { IController } from '../shared/protocols/controller'

export const adaptRouteExpress = (controller: IController) => {
  // A função adaptRouteExpress é exportada para que possa ser 
  // utilizada em outros módulos da aplicação. Ela recebe um 
  // parâmetro controller, que é uma instância da classe que 
 //  implementa a interface IController.

  return async (req: Request, res: Response) => {
    // Retorna uma função assíncrona que será utilizada como 
    // callback para o roteamento no Express.js. A função callback 
    // recebe os parâmetros req (requisição) e res (resposta) do 
    // Express.js.

    const httpRequest: HttpRequest = {
      body: req.body
    }

    // Estamos adaptando a estrutura de dados da requisição 
    // recebida pelo Express.js para o formato esperado pela 
    // interface HttpRequest. Neste caso, estamos apenas pegando o 
    // corpo da requisição (req.body) e atribuindo ao campo body 
    // do objeto httpRequest.

    const httpResponse = await controller.handle(httpRequest)
    res.status(httpResponse.statusCode).json(httpResponse.body)

    // A resposta obtida do controller é adaptada para o formato 
    // esperado pelo Express.js. Utilizamos os métodos status e 
    // json do objeto res para definir o status code HTTP da 
    // resposta e enviar o corpo no formato JSON para o client.
  }
}
Enter fullscreen mode Exit fullscreen mode

Agora precisamos utilizar o adapter criado. No arquivo signUp.routes.ts faça as alteração necessárias para ultilizar o adaptador:

Antes:

import { Router } from 'express'
import { CreateSignUpFactory } from '../../../application/modules/SignUp/useCases/CreateSignUp/CreateSignUpFactory'
const signupRoutes = Router()

signupRoutes.post('/signup', (req, res) =>  CreateSignUpFactory().handle(req, res))

export { signupRoutes }
Enter fullscreen mode Exit fullscreen mode

Depois:

import { Router } from 'express'
import { CreateSignUpFactory } from '../../../application/modules/SignUp/useCases/CreateSignUp/CreateSignUpFactory'
import { adaptRouteExpress } from '../../../infra/adapters/adaptRouteExpress'
const signupRoutes = Router()

signupRoutes.post('/signup', adaptRouteExpress(CreateSignUpFactory()))

export { signupRoutes }
Enter fullscreen mode Exit fullscreen mode

Criando o adaptador para o Fastify

No arquivo adaptRouteFastify.ts insira o código abaixo:

Aqui a estrutura é a mesma com uma pequena diferença: a tipagem usada é a do fastify naturalmente.

import { FastifyRequest, FastifyReply } from 'fastify'
import { HttpRequest } from '../shared/protocols/http'
import { IController } from '../shared/protocols/controller'

export const adaptRouteFastify = (controller: IController) => {
  return async (req: FastifyRequest, res: FastifyReply) => {
    const httpRequest: HttpRequest = {
      body: req.body
    }
    const httpResponse = await controller.handle(httpRequest)
    res.status(httpResponse.statusCode).send(httpResponse.body)
  }
}
Enter fullscreen mode Exit fullscreen mode

Agora precisamos utilizar o adapter criado. No arquivo index.ts que fica dentro da pasta fastify responsável pelas rotas(src/infra/routes/fastify/index.ts) faça as alteração necessárias para ultilizar o adaptador:

Antes:

import { FastifyPluginAsync } from 'fastify'
import { CreateSignUpFactory } from '../../../application/modules/SignUp/useCases/CreateSignUp/CreateSignUpFactory'


export const signUpRouter: FastifyPluginAsync = async (
  fastify
): Promise<void> => {
  fastify.post('/signup', (req, res) => CreateSignUpFactory().handle(req, res))
}
Enter fullscreen mode Exit fullscreen mode

Depois:

import { FastifyPluginAsync } from 'fastify'
import { CreateSignUpFactory } from '../../../application/modules/SignUp/useCases/CreateSignUp/CreateSignUpFactory'
import { adaptRouteFastify } from '../../../infra/adapters/adaptRouteFastify'

export const signUpRouter: FastifyPluginAsync = async (
  fastify
): Promise<void> => {
  fastify.post('/signup', adaptRouteFastify(CreateSignUpFactory()))
}
Enter fullscreen mode Exit fullscreen mode

Testando a aplicação

Agora que já temos os adaptadores das rotas podemos testar se nossa aplicação vai funcionar tanto com Express quanto com Fastify.

Testando com Express

Coloque o valor express para a variável SERVER_TYPE no arquivo .env

SERVER_TYPE=express
PORT_SERVER=5000
Enter fullscreen mode Exit fullscreen mode

Execute o comando yarn start:dev no terminal. Teste a requisição no insomnia ou qualquer outra ferramenta, se tudo estiver correto teremos esse resultado:

resultado requisição

O status code retornado é o 201 que foi definido na função create no arquivo httpHelper.ts o body stá vázio porque não definimos mensagem de criação bem sucedida.

Testando com Fastify

Pare a aplicação e altere o valor da variável SERVER_TYPE para fastify(no arquivo .env).

Execute novamente o comando yarn start:dev no terminal. Teste a requisição no insomina ou qualquer outra ferramenta. O resultado obtido deverá ser o mesmo do anterior demonstrado no print acima.

Conclusão

Como prometido temos agora uma aplicação que funciona tanto com fastify quanto com express mudando apenas uma variável de ambiente(SERVER_TYPE), sem ser necessário alterar nosso código principal. Nossa camada de domínio(entidades e usecases dentro da pasta aplication) não precisa saber que ferramentas externas estamos usando, isso não interessa.

Se quisermos usar outro framework que não o express ou o fastify não será necessário alterar código na nossa camada de domínio, apenas na camada de infraestrutura.

Ainda temos alguma coisas pra melhorar na nossa aplicação que será feito nos próximos artigos. Até breve.

💖 💪 🙅 🚩
zorasantos
Zoranildo Santos

Posted on August 1, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related