Integrando o Prisma 7 com Supabase
Oi turma, tudo certinho?
Estou escrevendo essa publicação para tentar ajudar as pessoas que eventualmente poderiam ter o mesmo problema que eu.
O problema...
Eu queria integrar a minha API que usa o Prisma ORM v7 com um banco PostgreSQL com Supabase. As orientações de conexão do Supabase são essas:
.env
# Connect to Supabase via connection pooling
DATABASE_URL="postgresql://postgres.[PROJECT_ID]:[YOUR-PASSWORD]@aws-1-us-east-1.pooler.supabase.com:6543/postgres?pgbouncer=true"
# Direct connection to the database. Used for migrations
DIRECT_URL="postgresql://postgres.[PROJECT_ID]:[YOUR-PASSWORD]@aws-1-us-east-1.pooler.supabase.com:5432/postgres"
schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
directUrl = env("DIRECT_URL") # Aqui está o bendito problema
}
Acontece que eu estou usando o Prisma 7, a última versão do ORM exige que as configurações sejam feitas a partir do arquivo de configurações do ORM prisma.config.ts e simplesmente REMOVEU a variável de configuração directUrl, ou seja, a documentação do Supabase ainda está alinhada com a versão 6 do Prisma.
Ok, e daí?
Com minha teimosia eu decidi que iria rodar as migrations com a URL padrão da porta 6543, acontece que essa porta está em Transaction Mode, o Prisma tenta usar Prepared Statements ou criar tabelas de controle que o Pooler do Supabase (PgBouncer) não consegue gerenciar nesse modo, o que faz a conexão ficar "pendurada" (idling) ou retornar erro de protocolo.
Sim, óbvio... É só rodar na outra URL de conexão que está em Migration Mode (5432) e pronto, né? Exato! Agora eu só precisava dizer isso para o meu servidor node... COMO QUE ELE IRIA TROCAR AS VARIÁVEIS?!! Uma hora a DATABASE_URL e outrora a DIRECT_URL.
Solução
Eu criei um npm scriptpara facilitar as migrations e alinhado com o meu prisma.config.tsficou assim:
prisma.config.ts
import "dotenv/config";
import { defineConfig } from "prisma/config";
const isSupabaseMigrate = process.env.PRISMA_USE_DIRECT_URL === "1";
console.log(`DEPLOYING TO ${isSupabaseMigrate ? "DIRECT_URL" : "DATABASE_URL"}`);
const databaseUrl = isSupabaseMigrate
? process.env.DIRECT_URL ?? process.env.DATABASE_URL
: process.env.DATABASE_URL ?? process.env.DIRECT_URL;
if (!databaseUrl) {
throw new Error("DATABASE_URL or DIRECT_URL must be set");
}
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
},
datasource: {
url: databaseUrl,
},
});
package.json
"scripts": {
"migrate:supabase": "PRISMA_USE_DIRECT_URL=1 DEBUG=prisma:migrate,prisma:engine npx prisma migrate deploy",
},
Prontinho, agora quando eu rodo o script para migrations o Prisma sabe que eu quero apontar para o DIRECT_URL.
Espero ter ajudado ou entretido alguém. Abraços!!