Executando verificação de segurança...
3

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!!

Carregando publicação patrocinada...