@chrono-os/prisma-nest
v0.1.1
Published
Prisma 7 + Postgres sem os dois footguns: driver adapter impossível de esquecer e boot que prova o banco com SELECT 1 (o $connect() virou no-op). Fábrica do PrismaPg, ping reutilizável e PrismaService para NestJS.
Downloads
296
Maintainers
Readme
@chrono-os/prisma-nest
Prisma 7 com Postgres (@prisma/adapter-pg) sem os dois erros que o parque já pagou em separado: esquecer o driver adapter e confiar no $connect(). Entrega a fábrica do adapter, um ping reutilizável por health check e a classe base do PrismaService para NestJS.
Os dois footguns
1. super() sem adapter só quebra em runtime. No Prisma 7, new PrismaClient() sem driver adapter lança A driver adapter is required. O typecheck passa. Em class PrismaService extends PrismaClient, quem instancia é o super(), que nem aparece num grep por new PrismaClient. Aqui o super() é do pacote e sempre recebe o adapter.
2. $connect() virou no-op. Com driver adapter, $connect() só cria o pool do pg, que é preguiçoso, e resolve com o banco fora do ar (medido em 71 ms contra endereço morto no painel-conteudo; o teste tests/prisma-real.test.ts reproduz). O try/catch em volta dele é código morto e o log "Database connected" mente. O boot deste pacote roda SELECT 1 com timeout.
Nest
import { Injectable } from '@nestjs/common'
import { PrismaClient } from '@prisma/client' // ou o caminho do seu `output`
import { createPrismaService } from '@chrono-os/prisma-nest/nest'
@Injectable()
export class PrismaService extends createPrismaService(PrismaClient, {
politicaBoot: 'avisar', // 'falhar' derruba o boot se o banco não responder
timeoutPingMs: 5000,
adapter: { max: 10, connectionTimeoutMillis: 5000 },
client: { log: ['error'] }, // resto das opções do PrismaClient, menos `adapter`
}) {}'avisar'(default) loga e sobe; rotas com banco falham até ele voltar e o/healthconta a verdade.'falhar'faz o bootstrap do Nest rejeitar.adapteraceita uma função, avaliada no construtor, para ler um env validado sem tocar nele no import:adapter: () => ({ url: env.DATABASE_URL }).onModuleDestroychama$disconnect(), que fecha o pool. O Nest só chama esse hook no SIGTERM se omain.tstiverapp.enableShutdownHooks().
Fora do Nest (singleton, worker, script, Fastify)
import { criarAdapterPg, pingBanco, verificarBancoNoBoot } from '@chrono-os/prisma-nest'
export const prisma = new PrismaClient({ adapter: criarAdapterPg() })
await verificarBancoNoBoot(prisma, { politica: 'falhar' })
health.registrar('db', pingBanco(prisma, 2000)) // () => Promise<{ latenciaMs }>O entry raiz não importa Nest.
criarAdapterPg(opts)
| Opção | Default | Nota |
|---|---|---|
| url | process.env.DATABASE_URL | Lida na chamada, nunca no import. |
| max | 10 | Teto do pool por client. Dois clients no mesmo processo somam. |
| connectionTimeoutMillis | 5000 | O default do pg é 0, que espera para sempre. |
| ssl | não definido | Se a URL tiver sslmode= ou ssl=, a URL vence (regra do pg). |
| schema | não definido | PrismaPgOptions.schema. |
| permitirSemUrl | false | Sem URL, usa um placeholder que nunca conecta em vez de lançar. |
| onPoolError | loga via logger.error | Conexão ociosa que morreu (Postgres reiniciado). |
| pg | | Qualquer outra chave do pg.PoolConfig. |
Credencial fora de log e erro
Nenhuma mensagem do pacote inclui a URL. Erro de ping e de boot passa por mascararSegredos: a URL conhecida vira [DATABASE_URL], a senha solta vira *** e qualquer postgres://user:senha@ restante perde a senha. O erro que sai do pingBanco é um Error novo (com o code do Prisma preservado), sem o objeto original.
Testes
yarn test gera o client do schema de teste e roda unit + Prisma real contra endereço morto. A integração com Postgres de verdade roda com PRISMA_NEST_IT_URL definida (instruções em tests/integracao-pg.test.ts).
