-
Notifications
You must be signed in to change notification settings - Fork 59
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
Thoughts on resolver forwarding #40
Comments
I think the biggest issue with posts(
where: PostWhereInput
orderBy: PostOrderByInput
skip: Int
after: String
before: String
first: Int
last: Int
): [User]! |
@SpaceK33z No, that's not the case. You can just import it, by putting |
Thanks, I did not know that 😅. Still learning GraphQL... |
Would it be possible to compare GraphQL schemas between the database and application using introspection and then determine which application queries don't have resolvers? |
@kbrandwijk Import doesn't automatically expose the imported type to client. It's only referencing, that being said, I still need to redefine the type to expose to the client. My concerns is, say, I want to be able to expose automatically all the generated type from |
@marktani I have no problem on performing auth checking using forwardTo. Instead of wrapping per node basis, I would wrap all the resolvers before passing it GraphQLServer configuration. My concern now is what I state on my previous comments |
@arrowfunxtion wrapping all of the resolvers with an auth check works if every query requires authentication. It's doesn't work if you want per query authentication. |
@ramsaylanier Nope, it works per query too. Basically the wrapper will check if the particular query needs an auth or authorization (defined in separate files, I called policies.js). If there is policy defined, then use the policy function, if not, let it pass |
This blog post offers potential simple solutions to these issues: https://medium.com/@lastmjs/advanced-graphql-directive-permissions-with-prisma-fdee6f846044 It shows a simple way to automatically expose all generated queries and mutations, and to easily combine those with your own custom schema and resolvers. Copying schema information is kept to a minimum. Permissions are handled elegantly through custom directives. Let me know if you have any questions. |
Not sure if this is the place to share, but I posted a PR #65 which adds an optional allPosts: forwardTo('db', 'posts') Basically, allow forwarding to db endpoints whose name doesn't match the app endpoint. |
That's a great suggestion and already a good step in the direction which I've laid out in this comment. |
@timsuchanek has written up some thoughts on how to push this forward. Curious to hear more thoughts on this: #83 |
Hi! So what is the current status of this issue? is there a recommended approach for that? |
Bump, also interested in a minimal stack approach reducing duplicated schema code and trivial resolvers :) |
Update: We're currently working on a new kind of GraphQL server framework which doesn't require you duplicate your schema/resolver code while still making it easy to adjust/evolve your schema in an easy and (type-)safe way. (The best part: you won't have to think about schema delegation or mess with the |
Hi @schickling, Can't wait to see it as a core feature. Thanks! |
For simple CRUD operations which happen often, having to specify resolvers is still cumbersome even with Would be cool to have some sort of config that lets you set |
Hey @webberwang, this is a great point! Have you seen Here is a simple example that shows how to setup a CRUD API for your Prisma models: datamodel.prisma type User {
id: ID! @id
email: String! @unique
name: String
posts: [Post!]!
}
type Post {
id: ID! @id
createdAt: DateTime! @createdAt
updatedAt: DateTime! @updatedAt
published: Boolean! @default(value: false)
title: String!
content: String
author: User!
} index.ts (GraphQL server code) const Query = prismaObjectType({
name: 'Query',
definition(t) {
t.prismaFields(['*'])
},
})
const Mutation = prismaObjectType({
name: 'Mutation',
definition(t) {
t.prismaFields(['*'])
},
})
const schema = makePrismaSchema({
types: [Query, Mutation],
prisma: {
datamodelInfo,
client: prisma,
},
} schema.graphql (generated) type Mutation {
createPost(data: PostCreateInput!): Post!
createUser(data: UserCreateInput!): User!
deleteManyPosts(where: PostWhereInput): BatchPayload!
deleteManyUsers(where: UserWhereInput): BatchPayload!
deletePost(where: PostWhereUniqueInput!): Post
deleteUser(where: UserWhereUniqueInput!): User
updateManyPosts(data: PostUpdateManyMutationInput!, where: PostWhereInput): BatchPayload!
updateManyUsers(data: UserUpdateManyMutationInput!, where: UserWhereInput): BatchPayload!
updatePost(data: PostUpdateInput!, where: PostWhereUniqueInput!): Post
updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput!): User
upsertPost(create: PostCreateInput!, update: PostUpdateInput!, where: PostWhereUniqueInput!): Post!
upsertUser(create: UserCreateInput!, update: UserUpdateInput!, where: UserWhereUniqueInput!): User!
}
type Query {
node(id: ID!): Node
post(where: PostWhereUniqueInput!): Post
posts(after: String, before: String, first: Int, last: Int, orderBy: PostOrderByInput, skip: Int, where: PostWhereInput): [Post!]!
postsConnection(after: String, before: String, first: Int, last: Int, orderBy: PostOrderByInput, skip: Int, where: PostWhereInput): PostConnection!
user(where: UserWhereUniqueInput!): User
users(after: String, before: String, first: Int, last: Int, orderBy: UserOrderByInput, skip: Int, where: UserWhereInput): [User!]!
usersConnection(after: String, before: String, first: Int, last: Int, orderBy: UserOrderByInput, skip: Int, where: UserWhereInput): UserConnection!
}
# ... and all other generated Prisma types Also feel free to check out this 15min demo video that shows how to get started with |
@nikolasburk Thank you for the informative demo code. I have actually looked into the code-first approach. While it sounds great to have the single source of truth to be in the actual programming language, the syntax just isn't as appealing as SDL. Would it be possible to use Edit: I was able to use |
Exactly, I'm pretty disappointed in Prisma's new direction |
That's a great point, I definitely agree that SDL is extremely nice to read! I personally prefer having a type-safe API over an untyped string-based API to construct my schema. For me, it's enough that the SDL is generated and I can use it as foundation to discuss the API with my colleagues, I don't need it when initially implementing the schema. But that's just my subjective opinion and I think the other one is equally valid – so SDL-first by all means remains a valid approach for building GraphQL servers! I also want to point out that while we believe that code-first is an amazing approach that solves a lot of problems, it is totally possible to keep using Prisma when building your schema SDL-first! This might require some more boilerplate (which can be alleviated by codegen tools like |
I'm glad SDL first is still possible. As for the argument about type safety, why can't someone just create plugins based off of the TypeScript language server or whatever that is called, but for the GraphQL language. TypeScript only gives you type safety because of the language tools around it. For example, lit-plugin uses those TypeScript tools to provide static type checking for HTML. I'm pretty sure the same kind of thing could be done for GraphQL |
@lastmjs You can generate types from @nikolasburk Are there examples of how the front end Or does nexus allow Instead of
|
Thank you for reporting. In the last few months, since the transition of many libraries under The Guild's leadership, We've reviewed and released many improvements and versions to graphql-cli, graphql-config and graphql-import. We've reviewed What we've found is that the new GraphQL Mesh library is covering not only all the current capabilities of GraphQL Binding, but also the future ideas that were introduced in the original GraphQL Binding blog post and haven't come to life yet. And the best thing - GraphQL Mesh gives you all those capabilities, even if your source is not a GraphQL service at all! Just like GraphQL Binding, you get a fully typed SDK (thanks to the protocols SDKs and the GraphQL Code Generator), but from any source, and that SDK can run anywhere, as a connector or as a full blown gateway. If you think that we've missed anything from GraphQL Binding that is not supported in a better way in GraphQL Mesh, please let us know! In the context of that particular issue - GraphQL Mesh uses a few interesting mechanisms like We're looking forward for your feedback of how we can make your experience even better! |
Based on recent feedback, I'd like to kickstart an open discussion about the state of resolver forwarding and potential improvements.
forwardTo
is a great convenience function:Here, we forward the
posts
query from our GraphQL server to a Prisma API.However, as soon as we want to modify the behaviour by, say, checking authentication before resolving, we have to fall back to the full
ctx.db.query
call:The best way to tackle this at the moment is to write a little convenience wrapper to check authentication like so:
Can you come up with other scenarios where resolver forwarding falls short, and approaches to improve the entire experience surrounding resolver forwarding?
#37 is a great idea in that direction, but I'm sure there are more great approaches to be found 🙂
The text was updated successfully, but these errors were encountered: