-
Notifications
You must be signed in to change notification settings - Fork 423
Description
Feature Request
Is your feature request related to a problem? Please describe.
I am using Prisma and the PrismaModule as my ORM. It's so thorough and easy that I'd like to avoid wrapping queries/mutations with my own logic until much later. But some queries/mutations must be wrapped, such as wrapping the unsafe createUser mutation to a safer register mutation. As a result, my front-end is looking at having two graphql clients: one for the prisma server and one for the nestjs-exposed resolvers.
"Exposing your prisma server is like exposing your database" is a valid point I have seen, but that seems to be mostly because they're hard to protect. Making guards work with Prisma endpoints may alleviate this concern. If the exposure of these queries/mutations can be controlled by nestjs, then they will be easier to secure and restrict access.
Describe the solution you'd like
I'd like to be able to expose certain Prisma queries/mutations (such as createPost and updatePost), restrict others (such as createUser), and implement my own (login, register, incrementFoo, etc.) for a single prisma model from a single resolver, like how Controllers currently work. Preferably, these would all be exposed and managed by nestjs (with guards, middleware, pipes, etc.) so that only one client is needed for the nestjs-exposed endpoint.
One thing that came to mind is an extendable PrismaResolver. I see this being used as something like
export class PostResolver extends PrismaResolver {
constructor() {
/* tell the PrismaResolver what the prisma model is called */
}
// post and posts are already present as queries unless specified manually
// createPost, updatePost, and deletePost are already present as mutations unless specified manually
// custom mutation
@Mutation()
public async incrementFoo = () => {
/* prisma logic for incrementing a field */
}
// restricted mutation
@Mutation()
@UseGuards(AuthGuard, AdminRoleGuard)
public async createPost(...args) {
const result = await this.prisma.createPost(...args);
/* do something with the result */
}
// a prisma mutation that is not exposed
// no deletion allowed
@Ignore()
public async deletePost = () {}
// allow posts to be unpublished
@Mutation()
public async unpublishPost = () => {
/* set the post's published field to false */
}
}
Teachability, Documentation, Adoption, Migration Strategy
The image of using the suggested PrismaResolver is remniscient of creating a custom TypeOrm repository that extends the default implementation. Other possibilities that lead to the same functionality would also work.
What is the motivation / use case for changing the behavior?
- Allow for securing and restricting well-made queries/mutations that already exist
- Allow for adopting a "fill-in-the-blanks" mentality to supplement missing queries/mutations. We all likely need foo, foos, createFoo, updateFoo, and deleteFoo routes. We also just as likely need custom queries/mutations like register and login. These should all be available from one server and one POST endpoint.
- Gives an extra option to nestjs/prisma users (does not remove existing options)