Pr0m3th3us
Pr0m3th3us

Reputation: 21

CRUD Generic Wrapper for Prisma Service

I am creating an API using NestJS and Prisma.

To manage the different models, I would like to create CRUD wrapping functions in different entity services, as adaptive as the Prisma client functions when it comes to use select or include options.

Here is what I have so far:

type IncludeOptions = Prisma.ProviderInclude | undefined;
type SelectOptions = Prisma.ProviderSelect | undefined;

@Injectable()
export class ProviderService {
  constructor(private readonly prisma: PrismaService) {}

  async get<T extends IncludeOptions, U extends SelectOptions>(
    where: Prisma.ProviderWhereUniqueInput,
    addons: { include?: T; select?: U } = {},
    throwOnNotFound = false,
  ): Promise<
    Prisma.ProviderGetPayload<{
      include?: T;
      select?: U;
    }>
  > {
    const provider = this.prisma.provider.findUnique({
      where,
      ...addons,
    });

    if (!provider && throwOnNotFound) {
      throw new NotFoundException(ApiErrorCode.PROVIDER_NOT_FOUND);
    }

    return provider;
  }

  async create<T extends IncludeOptions, U extends SelectOptions>(
    data: Prisma.ProviderCreateInput,
    addons: { include?: T; select?: U } = {},
  ): Promise<
    Prisma.ProviderGetPayload<{
      include?: T;
      select?: U;
    }>
  > {
    return this.prisma.provider.create({
      data,
      ...addons,
    });
  }

  async update<T extends IncludeOptions, U extends SelectOptions>(
    where: Prisma.ProviderWhereUniqueInput,
    data: Prisma.ProviderUpdateInput,
    addons: { include?: T; select?: U } = {},
  ): Promise<
    Prisma.ProviderGetPayload<{
      include?: T;
      select?: U;
    }>
  > {
    return this.prisma.provider.update({
      where,
      data,
      ...addons,
    });
  }
}

I can use it like this:

const selectedData = Prisma.validator<Prisma.ProviderSelect>()({
  id: true,
  email: true,
  info: {
    select: {
      firstName: true,
      lastName: true,
    },
  },
});

const provider = await this.providerService.get({ id }, { select: selectedData }, true);

It does not raise any error. But still, it does generate the right response type, which would be in this case:

{ id: string; email: string; } & { info: { lastName: string; firstName: string } }

Does anyone have already tried to do that and can guide me pls ?

Upvotes: 2

Views: 1145

Answers (1)

Sanzhar Dan
Sanzhar Dan

Reputation: 393

As of now, Prisma doesn't well support creating a generic CRUD class natively.

I found this thread to be useful and built my solution on top of it - https://github.com/prisma/prisma/issues/5273

Upvotes: 0

Related Questions