How handle very similar services but with some variations using Nest.js and Prisma?

Viewed 20

So, I'm building an API using Nest.js and Prisma to communicate with a MongoDB instance. Some of my collections at MongoDB are very similar, but they have some different fields. Let's say they are all fruits, but each fruit have a few different properties. At first, I was creating a Nest.Js controller and a service for each of the fruits I have, but I noticed that all of the services were VERY similar. So I had the ideia of creating a generic service that could work with all the fruits types. For example, I created a service called default-fruit.service.ts. I defined a type called DefaultFruit, which is defined by: type DefaultFruit = Banana | Orange | Lemon, (and some variations, like type PromiseDefaultFruit, type ArrayDefaultFruit, etc). This way, if I wanted to get all the items of a collection I would have a method in this service this way:

async getFruits(type: FruitType): Promise<ArrayDefaultFruit> {
    return type === 'banana' ? this.prisma.bananaCollection.findMany({})
      : type === 'orange' ? this.prisma.orangeCollection.findMany({})
      : this.prisma.lemonCollection.findMany({});
  }

Well, it is actually working, but it feels wrong and unefficient, since each little variation I want to do for a specific type I have to do many hardcoded ifs (in my real case, there are 4 different types). So, everytime I want to access the correct prisma collection I have to do as the example above, and also if I have a little variation for a type in a method I have to keep using ifs.

I tried to create a method to return the correct prisma service, so I could reduce the ifs a little bit, as the example below:

getService(type: FruitType) {
    return type === 'banana' ? this.prisma.bananaCollection
           : type === 'orange' ? this.prisma.orangeCollection
           : this.prisma.lemonCollection
  }

And then use it like:

async getFruits(type: FruitType): Promise<ArrayDefaultFruit> {
     return this.getService(type).findMany({});
}

But I get a type error from prisma:

This expression is not callable. Each member of the union type '((args?: SelectSubset<T, bananaCollectionFindManyArgs>) => CheckSelect<...>) | ((args?: SelectSubset<...>) => CheckSelect<...>) | ((args?: SelectSubset<...>) => CheckSelect<...>) | (<T extends req...' has signatures, but none of those signatures are compatible with each other.

Anyway, even if it worked, don't know with this is the best way to do it, I feel like what I'm doing is just many work arounds. Also, it gets harder and harder if I wanted to add more fruits later.

What I wanted to know is: what is the best way to work this kind of situation out? How would you do it? And also, is it possible to select a generic prisma service as a tried to do in the example above without receiving type errors?

Thanks for any help.

0 Answers
Related