zenstack
zenstack copied to clipboard
[Feature Request] Allow overridding of model properties when importing
Currently, imports are tightly coupled to each other because Prisma requires the relationship to be defined on both sides using the other-sides type. However, each model may be defined in a separate module where it's desirable to treat them as if they are isolated.
One way to resolve this could be to allow an abstract models properties to be overridden by the concrete class, kind of like an override
in javascript. Currently, if you try to override a property that was defined in an abstract model it will error with Duplicated declaration name
.
I think there's a good use-case for this feature if you consider it from the perspective of an NPM package, which could export an abstract model it expects you to extend, but would also allow you to override the properties relation types with custom ones, as long as their interfaces matched.
Here is a somewhat arbitrary example to illustrate what I'm thinking..
schema.zmodel - @someOrg/UserPlugin
abstract model AbstractProfile {
id String @id @unique @default(uuid()) @db.Uuid
firstName String
lastName String
// Relation
user AbstractUser
}
abstract model AbstractUser {
id String @id @unique @default(uuid()) @db.Uuid
email String @unique
password String @db.Char(97)
profileId String @unique @db.Uuid
// Relation
profile AbstractProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
}
schema.zmodel - App
import '@someOrg/UserPlugin'
/** User adds additional fields */
model User extends AbstractUser {
isLocked Boolean @default(false)
lastLogin DateTime @default(now()) @map("last_login")
// Relation
profile Profile @relation(fields: [profileId], references: [id], onDelete: Cascade)
}
/** Profile adds additional fields */
model Profile extends AbstractProfile {
email String @unique @Validator.IsEmail()
title String?
phone String? @Validator.IsPhoneNumber()
mobile String? @Validator.IsPhoneNumber()
image String? @Validator.IsUrl()
locale String? @default("en") @Validator.IsLocale()
// Relation
user User
}
Right now, you either define the relation in the abstract, which means it's fixed to what model it references and you lose reference to the additional fields when being returned from the plugin. Or, you leave it out of the abstract and only define the relation in the concrete model. But doing this means that the plugin cannot rely on the relationship existing in it's own code.
If you could override as shown above, the plugin can use its internal representation of an "extended" User
and Profile
to code against and still have it match the user's App version when returned from prisma/client just with additional fields.
Maybe this is already possible, and I'm missing something or thinking about it incorrectly. I'm open to suggestions, but I'm trying to find a way to handle relations when the two schemas are separated by a @Module. I need to define the relationship for permissions that require access through a predicate, for example, but don't necessarily care about knowing all of the model's other properties that might be specific to the app.