@seta-labs/nestjs-prisma
v0.2.0
Published
Prisma for NestJS APIs on Postgres: a PrismaService built on the app's generated client (env check, pool with fail-fast, serialized interactive transactions, lifecycle logs), a database health indicator and the P2002/P2025 error predicates
Downloads
817
Readme
@seta-labs/nestjs-prisma
Prisma for NestJS APIs on Postgres (Prisma 7, @prisma/adapter-pg): the app's PrismaService built on its own generated client, a database health indicator for @seta-labs/nestjs-health, and the predicates repositories use to translate P2002/P2025 ([L1]). Optional: BLUEPRINT.md states the contracts, this package is one way to meet them.
Install
pnpm add @seta-labs/nestjs-prismaPeer dependency: @nestjs/common. The package imports nothing from Prisma: the app passes its generated PrismaClient and PrismaPg.
Wire it
// src/prisma/prisma.service.ts: stays in the app, where the client is generated
import { Injectable } from '@nestjs/common';
import { PrismaClient, PrismaPg } from '@acme/db';
import { prismaService } from '@seta-labs/nestjs-prisma';
@Injectable()
export class PrismaService extends prismaService(PrismaClient, { adapter: PrismaPg }) {}// app.module.ts
import { HealthModule } from '@seta-labs/nestjs-health';
import { DatabaseHealthIndicator, PrismaModule } from '@seta-labs/nestjs-prisma';
@Module({
imports: [
PrismaModule.forRoot({ service: PrismaService }), // global: inject PrismaService anywhere
HealthModule.forRoot({ service: 'my-api', indicators: [DatabaseHealthIndicator] }),
],
})
export class AppModule {}What the service does on top of the generated client:
DATABASE_URLis required at construction (a clear boot error, not a failed first query); its?schema=becomes the adapter schema.- Pool:
maxfromPG_POOL_MAX(default10),idleTimeoutMillis30_000,connectionTimeoutMillis5_000so an exhausted pool fails fast instead of queueing forever. Override withpool: { … }, or the URL withconnectionString. - Interactive transactions run their queries one after the other (
serializeTransactionQueries): Prisma 7 may otherwise overlap them on the transaction's single connection and leave it stuck.serializeTransactions: falseturns it off. $connecton module init and$disconnecton shutdown, logged through the NestLogger.
Translate errors in repositories
import { ConflictException, NotFoundException } from '@nestjs/common';
import { isRecordNotFound, isUniqueViolation } from '@seta-labs/nestjs-prisma';
try {
return await this.prisma.order.create({ data });
} catch (err: unknown) {
if (isUniqueViolation(err, 'uq_orders_code')) throw new ConflictException('Order code taken');
throw err;
}isUniqueViolation(err, constraint?) finds the constraint in meta.target, or, when Prisma 7 with the pg adapter leaves it empty, in the driver message and the constraint columns. isRecordNotFound(err) matches P2025.
