Middlewares com Prisma
Como potencializar sua base de dados
Se você já utilizou o Express você sabe como é bom poder ter middlewares executando antes das suas rotas. Hoje temos algumas alternativas como os middlewares no Next.js, porém não é a mesma coisa ainda. Hoje lendo a documentação do Prisma me deparei com uma secção que ainda não tinha lido, os middlewares para o Prisma.
Esses middlewares possibilitam que executemos funções antes de realizarmos operações na nossa base de dados. Por exemplo, digamos que temos uma aplicação que tem a capacidade de criar usuários com email e senha, e essa operação pode ser originada de diversos locais diferentes da aplicação. Obviamente necessitamos criptografar a senha antes de armazena-la na base de dados. Podemos todas as vezes que formos executar a criação de um usuário garantir que estamos fazendo essa criptografia, porém no tamanho da aplicação que estamos falando, seria muito provável que em algum lugar passasse desapercebido sem ser criptografado. É ai que o middleware do Prisma entra em ação. É possível adicionarmos a seguinte função para interceptar as operações de criação de usuários.
import { PrismaClient } from "@prisma/client";
import { hash } from "bcryptjs";
const prisma = new PrismaClient()
prisma.$use(async (params, next) => {
if( params.model === "User" && params.action === "create" ) {
const hashedPassword = await hash(params.args.data.password, 10);
params.args.data.password = hashedPassword;
}
const result = await next(params)
return result
})
Essa simples função identifica quando estamos manipulando o modelo de usuários e quando a operação é de criação, e criptografa a senha que foi enviada para a base de dados. Esse é um exemplo bem simples, na documentação do Prisma você consegue achar alguns outros exemplos como logar operações e fazer soft delete.
Funcionamento
Vamos ver agora como que funciona e quais são os parâmetros que temos nos middlewares do Prisma.
params
-> É o parâmetro que contem todas as informações sobre a operação realizada, dados enviados, query, se foi executada em transaction, model que foi afetado, operação que foi executada entre outros.next
-> É a função que chama o próximo middleware da fila. Já que estamos falando dessa fila, na documentação há um exemplo muito interessante sobre com os middlewares são executados. Vou replica-lo aqui, mas você pode encontrar mais informações na documentação do Prisma
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient()
// Middleware 1
prisma.$use(async (params, next) => {
console.log(params.args.data.title)
console.log('1')
const result = await next(params)
console.log('6')
return result
})
// Middleware 2
prisma.$use(async (params, next) => {
console.log('2')
const result = await next(params)
console.log('5')
return result
})
// Middleware 3
prisma.$use(async (params, next) => {
console.log('3')
const result = await next(params)
console.log('4')
return result
})
const create = await prisma.post.create({
data: {
title: 'Bem vindo ao Prisma Day 2022',
},
})
const create2 = await prisma.post.create({
data: {
title: 'Prisma é fácil assim!',
},
})
Output
Bem vindo ao Prisma Day 2022
1
2
3
4
5
6
Prisma é fácil assim
1
2
3
4
5
6
Conclusão
Para finalizar quero só lembrar que, apesar de os middlewares do Prisma serem uma ferramenta muito útil, devemos ter alguns cuidados a utiliza-la. Primeiro, devemos sempre filtrar o modelo e o método que desejamos utilizar o middleware. Ter o middleware executando em todas as queries seria muito custoso e impactaria a performance. Outra dica é ver o seu caso de uso, o Prisma possui várias funcionalidades que podem substituir os middlewares em casos específicos, então sempre de uma lida na documentação para garantir que está usando a ferramenta adequada para o seu caso de uso.
Deixo aqui também o meu convite para o slack do Prisma , onde você pode interagir com milhares de desenvolvedores e uma comunidade ativa e apaixonada.