#create type at runtime in a service

9 messages · Page 1 of 1 (latest)

light rivet
#

this issue started of as a TS issue but it seems nest made it tougher to solve so gues this can count as a nestjs issue now?
i have this prisma issue have been stuck on for weeks now where i have my prisma/database service (call it what ever you want)
where i extend prisma with a custom findbyId method docs here
but that caused typescript to not regonize this custom method, prisma has a solution for this found here and that is to create a typing at run type (hate it) but then the issue with nest
i cant really create this typing at run time because i cant define it in the class but outside is not going to work either
so when i got another service that uses this databaseService i should be using this extended version but if i cant define it in the class our outside
let alone use it in the constructor of another service what am i supposed to do?

ps: I left out the onModuleInit and enableShutdownHooks out to keep things relative

@Injectable()
export class DatabaseService extends PrismaClient implements OnModuleInit {
  private readonly logger = new Logger(DatabaseService.name)

  constructor() {
    super()
    this.$extends({
      model: {
        $allModels: {
          async findById<T, A>(
            this: T,
            id: Prisma.Exact<A, Prisma.Args<T, 'findUniqueOrThrow'>['where']>,
          ): Promise<Prisma.Result<T, A, 'findUniqueOrThrow'>> {
            const context = Prisma.getExtensionContext(this)
            const result = await (context as any).findUniqueOrThrow({ where: { id } })
            return result
          },
        },
      },
    })
  }
}

so not only am i stuck with a TS issue i also got the nestjs problem where i can not create the typing because i'm working in a class here

Prisma

Extend the functionality of Prisma Client

sinful summit
#

Don't know how many times I have to give you some of the possible solutions... Also again, I would not recommend this, if you want active record, use an ORM that actually supports it properly.

  • Define an interface and use that instead when injecting your prisma client.
    • Use declaration merging. Downside is that if you inject the raw prisma client that you get types for something that doesnt exist.
  • Return the extended prisma client from the class and let it infer the type and use it like _service.getClient()
#

also you could probably do something like this to hack the system:

export class PrismaService extends PrismaClient {
  public constructor() {
    super();
    this.setup();
  }

  public setup() {
    return this.$extends({
      model: {
        user: {
          test() {
            return 0;
          },
        },
      },
    });
  }
}

type ExtendedPrismaClient = ReturnType<PrismaService['setup']>;

const a: ExtendedPrismaClient = new PrismaService();

a.user.test();
light rivet
# sinful summit Don't know how many times I have to give you some of the possible solutions... *...

somehow i knew you would reply first
sorry offending you for not seemingly listening to your advice
i tried to ask follow up question and giving extra context you also mentioned you where done with it
as far as i remember?
after giving you a week in time to reply you didn't
and the #1056608823219081266 channel more dead then the flys i killed in my life (that needs to be looked at btw)

and being stuck with this longer then i like to admit i moved my issue to here with the extra context included because i have been stuck not able to do anything else, you could call me desperate at this point

  • although i can understand your reasoning switching ORM would bring more issues with it then it would be worth
    besides what else is there other then Prisma and typeOrm?
  • i tried decloration merging already and learned those issues my self 😅
  • i'm going to need to look at this these 2, at this point my head hurts trying to make sense
    so i'm going to take a little break before i continue on those 2 suggestions

still appreciate the responses you just gave me blobheart

sinful summit
#

you could also ditch the extends idea and just pass it some kind of specification

light rivet
#

either way if i'm going to proceed with the custom method or just dont use it at all
the problem will be solved with either those 2 solutions

#

gues this answers it then