-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Convert the Models from Types to Classes #5998
Comments
Here are some monkey-patch hacks I've been playing around with This proxy class would be a parent class. It just copies a Model-Type-instance fields. One would implement addition functions inside here.
getDb basically return a Prisma client.
|
Is anyone using |
Have not heard of that package before =) Looks like it would work fine. If you have an explicit "data" layer that abstracts Prisma from the business logic, then all the "plainToClass" calls could be made there. If you this is not the case, then you would have to "plainToClass" them where ever the Prisma calls are made, or monkey-patch/override the Prisma functions. Prisma could potentially auto-generate default Class definitions for each model-type (ala index.d.ts) and utilize "plainToClass" to return object instances instead of JSON (perhaps via some configuration flag). There would have to be some convention as to where and how overrides/extensions of the generic Prisma Class definitions would be handled. Perhaps the Prisma generated Class definitions would be deposited in the application code somewhere, or developers would know where to look for them. |
I've recently came to the same conclusion that it would be much nicer to map the entities to your own classes than the awkward amount of mapping I'm currently performing especially when using I think the ideal API here would be to register/configure your classes with the client, you'd probably need the classes to conform to a specific interface for this to work but it would then use those returned models. Without looking too hard I wondered if a custom generator might be able to achieve this nicely. |
Same thing here. I want to work object orientated and have classes for my datatypes with some extra utility functions. |
It is already possible albeit with slight limitations on relations. A triavial example type yourWrapperType = {
validate(): boolean;
}
class UserWrapper{
constructor(ret:yourWrapperType, model: string, client: any){
Object.assign(this, ret);
}
validate() {
return true; //just for example always valid
}
}
const wrappers = {
[Prisma.ModelName.users]: UserWrapper
}
const prismaNew = prismaWrapper(prisma, wrappers);
//... somewhere else
const user = await prismaNew.users.findUnique({where: {id: 1}});
console.log('validation', user?.validate()); |
I tried wrapper a Player prisma type with a CPlayer class, which is very simple and would maybe work Anyone have a better solution? export class CPlayer {
data?: Player | null
constructor(data?: Player | null) {
this.data = data
}
// now we lose all typechecking
static async findOrCreate(query: Player): Promise<CPlayer> {
let data = await prisma.player.findFirst({ where: query })
if (!data) {
data = await prisma.player.create({ data: query })
}
return new CPlayer(data)
}
// move a player
async move(px: number, py: number) {
await prisma.player.update({
where: { id: this.data!.id },
data: { px, py },
})
}
} |
Hey everyone, I am excited to share that we have a proposal for this. With the Prisma Client Extensions, you will be able to extend your results so that you can add properties and methods to them. That's not all, we want to enable you to extend any layer of your Prisma Client. I'd love to get your feedback on the proposal and find ways to make it better. |
Unfortunately, the built-in prisma doesn’t really give the flexibility needed to directly convert the types to classes. I ended up creating some mappers from the type to class which can convert backwards and forwards the classes to models and vise versa Taking a note from the Java and C# worlds, this is a common practice to remap your classes to or from a database parameter set I’m not a fan of the proposed auto-map solutions as they don’t really allow for complex type mappings Take a model such as below:
An auto-mapper (such as
At this point, you may as well use the built in types from Prisma. The downside here is that if you eventually want to pull the My expected output would be
This format allows for downstream services to access and check the same field everywhere As this is a backend task, I think it would be beneficial to follow backend principles when accessing data; namely separating concerns in the following layers:
Wherein there is a one-way relationship. Users communicate with the API layer, which in turn communicates with the Service layer, which handles negotiations in the DB layer The service layer, converts the DTO objects to a prisma-compatible query, and returns the class objects as a response via common mappers Those mappers look something similar to this (as static methods of your Service class, or as exported constants of another file, my preferred approach)
This pattern would allow you to interact with prisma, and still work through your other classes with full support of prisma. The only caution here is that if your relation names change, you will need to ensure the mapper is properly in sync with your schema (ie. If my relation from user to organization is “organizationRelation” instead of “organization”, the mapper would need to have that type specified explicitly to make the map succeed This also allows you to ensure protected fields such as username or password are explicitly pruned from the return object instead of relying on a downstream service remembering to prune these values A more automated approach could use the experimental typescript decorators (similar to the TypeORM approach) to perform the map on a more generic scale for you |
To go back to the original request to be able to add fields to query results, this is now possible via Client Extensions and the Do I understand correctly though that there is a higher level use case than this specific one to be able to use Classes instead of Types that Prisma provides? |
I often use data classes, and have successfully used Prisma's power is in its inference. You just can't get the granular property inclusion when using something concrete like a class, especially when you introduce Your data classes will need to have every possible relation defined that you end up querying. So if you There are also considerations on whether your query is within a function. Returning the query as-is will allow the function caller to get inference. However, if you convert to a class instance within that function, you lose the granularity of Prisma's native query return type in exchange for a class instance with all the uncertainty regarding property inclusion. For me, I only convert to a class instance for client serialization where I can I recommend looking at the advanced type safety section of the Prisma docs; |
Problem
It would be great if an application can extend or monkey-patch/proxy additional properties onto the objects that are returned from the CRUD operations.
For example, I want to add some simple logical functions to the "User" model that is generated by Prisma. Each "User" that is returned from a Prisma CRUD operation would automatically have these user/application-defined functions or properties.
As far as I know, this is not possible with TypeScript "types".
If the models were classes, an application could add such functions to the class prototype. The objects returned from Prisma could be then extended to become full business/transfer objects.
Suggested solution
Make Prisma auto-generate classes in lieu of "types". Perhaps some conventions can be made so that Prisma automatically looks for any "class/model" overrides upon client instantiation.
Alternatives
I am writing some code that would automatically load up and wrap the Prisma model types with classes. It basically hijacks the "findFirst/findMany/etc." functions and supplants the return type with a Class object that can have application-specific properties.
However, I think this would be a valuable native Prisma feature.
Additional context
ORMs such as Django or Rails allow application developers to override/patch/extend the default ORM data models. Having Prisma be able to do this would make it easier for application developers to take a more OO approach.
The text was updated successfully, but these errors were encountered: