-
Notifications
You must be signed in to change notification settings - Fork 66
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
feature: ConnectionType supports custom fields #112
feature: ConnectionType supports custom fields #112
Conversation
These fields can be added to either the Connection or the Edge types
Awesome work @NeedleInAJayStack! So if I'm understanding correctly, the way to have custom connections or edges is to extend Will you update the Usage Guide with an example? |
I use the custom connection function to retrieve paginated objects from the database. How can I add custom field |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me 👍
Regarding that, I don't think making the Not 100% what is the best approach here. I am not sure what's the role of the built in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome!
I have a few initial ideas on this:
Thoughts? |
Not sure I understand the issue here. You can get the total count of edges by doing the same thing as in the added tests: extension Connection {
func total(context _: NoContext, arguments _: NoArguments) throws -> Int {
return edges.count
}
} Or if you want to read them from a database (which I assume is stored in the context), something like this is totally possible: extension Connection where Node == MyTableType {
func total(context: Context, arguments _: NoArguments) throws -> Int {
return context.db.run("SELECT COUNT(*) FROM my_table")
}
} Neither of these require a custom initializer. If you are using your own custom
I see the role of our |
@NeedleInAJayStack This seems like a solution. But how do I pass arguments with filters that are in the resolver? I need to calculate the total number taking into account the filters that are used for pagination. |
I agree. For example, if you had a connection for friends of a user (not necessarily the current user), how would you accomplish getting the total count? You might not want to query all the friends (it could be in the thousands), so And I'm not sure how you'd pass the originating user's |
Ok cool, still catching up. To make sure I understand - the issue is that within the Adding those in is definitely a tougher problem and maybe we hold off on these changes until we figure it out. I think cshadek gave some interesting approaches. If one of you would like to take a crack at it, I'd be happy to review! |
I can take a crack at it. Do you guys have a preference on which of the 3 options (not including 4) is the best way to go? My instinct says to go with (1) or (3) unless there's another better alternative. Option 1:
If we did use (1) what would be the best way to implement the dictionary? So for (1) you could have something like:
(I'm not sure about the naming, I also don't like using the strings instead of something more strongly typed. Is there a better way such as Option 3:
Option 3 could also be a good option for now. It takes care of a big use case by adding an optional
Option 5 (New idea):A 5th option would be to somehow let
A potential problem with this approach is that one parent object could have multiple fields that resolve to the same connection type, so you'd need a way to differentiate between the different fields. @NeedleInAJayStack @d-exclaimation @ZirgVoice What are your thoughts? Also how does a future desire to have connections of Unions and Interfaces affect this decision? |
The 5th option looks better and I think something like this would work for this |
I don't have a preference here. I think I would normally just use a custom connection and edge types if I need more that what it asked |
@d-exclaimation What about option 3 then? Or what if we made more of the inner connection logic accessible (slicing, etc). That way it would be easier to create custom connections. Maybe the standard should be to create custom connection and edge types, but at the same time, couldn't we make that process more efficient? @ZirgVoice It seems to me like option 5 could be very complex and requires a lot of changes. |
I like this idea, it make sense to allow user to have control over that. I haven't look into it so I don't know how difficult that may be.
I don't mind having that but I assumed the original design based on this, not sure if I want to go beyond that specifications (technically there's no restriction on additional fields) |
I think the issue stems from the fact that we can't really get to the What if we could do something like the following:
Then we can use the
I think this implementation would solve the issues that @ZirgVoice, @d-exclaimation and @NeedleInAJayStack mentioned. A user could then create the custom types as follows:
I'm not sure how this would work with This is just an initial idea and I haven't actually tested any code. Thoughts? |
@NeedleInAJayStack any thoughts? |
@cshadek, Sorry about the slow response, it's been a busy weekend 😀. WRT the exposing the slicing logic, one concern I have is that the slicing logic is based on having an array in memory prior to pagination, whereas that may not be true in some cases (loading from a database, for example). So more general closure-based tools may be better. The solution you outline above could work well too, but it is certainly a more complex API for the basic case. Honestly, the more I think about it, Connection stuff may live best in a separate "relay" extension package. In that case I think we would have more freedom to be creative and iterative with the implementation. If there's big difficulties in doing this as a separate package, we could prioritize extensibility in Graphiti. |
@NeedleInAJayStack sorry it's been a busy few weeks for me haha. I agree with this approach. It probably makes sense to keep Graphiti as close to the GraphQL spec as possible.
I agree with this approach as well. Should we just merge this as is and revisit in the future? |
@cshadek, no worries. Since this MR doesn't give us quite what we want, I think I'm going to close it. Thanks everyone for the great discussion here! |
These fields can be added to either the Connection or the Edge types