[Feature Request] Model-Level CRUD Hooks
Is your feature request related to a problem? Please describe.
- Prisma's current API for hooks (esp. at model level) is lacking.
.$extendsrequires explicit method wrapping, and doesn't support method-level extending.- Computed fields (which can cover some use-cases of READ hooks) are methods, and therefore unserializable - meaning, they're unable to be passed to the frontend unless explicitly called in the server
- Prisma Pulse is the current best solution, but is a separate third-party service (which currently only supports Postgres) and therefore may not be a practical solution for most.
- Zenstack's philosophy seems to jibe with locking down actions/logic to the model level, and therefore, thinking about implementing model-level CRUD hooks in the future may be appropriate
Example Usecases:
- Create: Famous Instagram-DB use-case of implementing a counter on a model-level field for # of likes as the db history of individual like objects is too big to cache. I.e., creation of
Likedocument would fire a hook that updates theirPostdocument. - Read: Some high-security apps need to keep read logs for everything an employee has accessed.
- Update: After updating
Usermodel with amembershiplevel, you may want to send the user an email thanking them for purchasing xyz subscription - Delete: cleaning up other model rows that may not be able to directly link to the deleted record for whatever reason
Describe the solution you'd like
- Definable-hooks applied at the
enhancecall, i.e. allowing the user to execute JS based on - Hooks will be fired even if I update a model via a call from a model above/below:
user.update({
data: {
subscription: {
create: {
// etc ...
}
}
}
})
- Post-MVP: Hooks would be able to access the prev/post document (or maybe you could have preX, postX hooks? - Post-Post-MVP may allow for pre hooks to cancel an action (pie-in-the-sky, I know ...))
- Post-MVP: provider the hook's function params access to the user that made the CRUD request. Useful for implementing read-logs etc.
Potential Challenges:
- AFAIK, there isn't an inbuilt API that wraps the Prisma core methods
- Determining when a model is CRUD'ed via a parent/children call may be tricky too
Comment from @ymc9
This is some thought background about access conrol. As for CRUD hooks, I fully agree with you that implementing with Prisma client extensions can be quite challenging given the flexibility of nesting - it's very easy to have a leaky implementation. I think it's a good idea that we "reimplement" some kind of hook at the TS-API land, like allowing you to provide simple callbacks when calling enhance (model + operation + action), and the API internally deals with traversing nesting, and probably also guarantees a transaction boundary.
For an idea of how this would work at a high level, have a look at keystone-js, which is also built on top of Prisma.
They're docs explain the implementation pretty well: https://keystonejs.com/docs/guides/hooks and the hooks api: https://keystonejs.com/docs/config/hooks