Skip to content

Instantly share code, notes, and snippets.

@houssenedao
Created February 13, 2024 15:41
Show Gist options
  • Save houssenedao/6e7c174f76e143a605ba9e486ba385f7 to your computer and use it in GitHub Desktop.
Save houssenedao/6e7c174f76e143a605ba9e486ba385f7 to your computer and use it in GitHub Desktop.
Unit of work pattern with prisma
import { Injectable } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
import { DefaultArgs, PrismaClientOptions } from '@prisma/client/runtime/library';
import { PrismaService } from '@shared/infrastructure/services';
import { LoggerServicePort, UnitOfWorkPort } from '@shared/infrastructure/ports';
import { ClsService } from 'nestjs-cls';
type TransactionFn = Parameters<PrismaClient['$transaction']>[0];
type TransactionOptions = Parameters<PrismaClient['$transaction']>[1];
export abstract class UowRepository implements UnitOfWorkPort {
abstract execute<T>(handler: () => Promise<T>): Promise<T>;
abstract getTransaction(): Omit<
PrismaClient<PrismaClientOptions, never, DefaultArgs>,
'$transaction' | '$connect' | '$disconnect' | '$on' | '$use' | '$extends'
>;
}
@Injectable()
export class PrismaUowAdapter extends UowRepository {
constructor(
private prisma: PrismaService,
private cls: ClsService,
private logger: LoggerServicePort,
) {
super();
}
async execute<T>(fn: TransactionFn, options?: TransactionOptions): Promise<T> {
this.logger.setContext(this.constructor.name);
return this.prisma.$transaction(async (tx) => {
this.cls.set('prismaTX', tx);
return (await fn(tx)) as Promise<T>;
}, options);
}
public getTransaction(): Omit<
PrismaClient<PrismaClientOptions, never, DefaultArgs>,
'$transaction' | '$connect' | '$disconnect' | '$on' | '$use' | '$extends'
> {
const transaction = this.cls.get('prismaTX');
if (!transaction) {
throw new Error(`database transaction not exist`);
}
return transaction;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment