-
-
Notifications
You must be signed in to change notification settings - Fork 922
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
connection should be non nullable #2581
connection should be non nullable #2581
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2581 +/- ##
==========================================
+ Coverage 83.40% 83.44% +0.03%
==========================================
Files 348 348
Lines 14024 14031 +7
Branches 2124 2125 +1
==========================================
+ Hits 11697 11708 +11
+ Misses 1750 1745 -5
- Partials 577 578 +1
Continue to review full report at Codecov.
|
Couple thoughts:
What's your take @SimonCropp ? |
how are you doing this? the current api doesnt make it easy, or i am missing something
yep, changing type could be breaking depending on how clients handle null=>notnull
I would prefer most thing defaulting to not null |
also should
actually be
? |
looks like the lgtm error is unrelated to my change? |
Just checked and although I thought they were non-null, I was wrong. I don't use the connection builder, so I just need to write my own
Sounds good to me
I agree. Now whether
Correct. It's been broken for some time, but I don't have permission to remove the plugin from github, nor the password (or time) to fix the problem on lgtm. |
no, the connection builder api has it hard coded as nullable |
Hmm. Maybe look at that. It would seem that either it should follow the pattern of other fields where you need to specify an explicit graph type (e.g. |
also updating cursor to be non null as per spec https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo.Fields |
i made edge and items not null |
Field<NonNullGraphType<StringGraphType>>("startCursor", "When paginating backwards, the cursor to continue."); | ||
Field<NonNullGraphType<StringGraphType>>("endCursor", "When paginating forwards, the cursor to continue."); |
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.
I don't think we can make these non-nullable. If there are no results, these would be null. See the reference specification schema. https://relay.dev/docs/guides/graphql-server-specification/
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.
consider me educated. i have reverted this
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.
I don't think we can make these non-nullable. If there are no results, these would be null. See the reference specification schema. https://relay.dev/docs/guides/graphql-server-specification/
There seems to be conflicting advice in the documentation. startCursor
and endCursor
are marked as nullable in the schema in the link you provided @Shane32 , but following the link to the GraphQL Cursor Connections spec suggests the opposite. Namely:
PageInfo must contain fields hasPreviousPage and hasNextPage, both of which return non-null booleans. It must also contain fields startCursor and endCursor, both of which return non-null opaque strings.
The Introspection of PageInfo in this doco lists all PageInfo
properties as "kind": "NON_NULL"
How do we tell which one is correct?
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.
Even within the spec it is confusing:
An “Edge Type” must contain a field called cursor. This field must return a type that serializes as a String; this may be a String, a Non-Null wrapper around a String, a custom scalar that serializes as a String, or a Non-Null wrapper around a custom scalar that serializes as a String.
Whatever type this field returns will be referred to as the cursor type in the rest of this spec.
So there it says that cursor fields may be nullable. But down below as you say, it explicitly says a "non-null string" and does not mention the words "cursor type" as quoted above.
I think that common sense must prevail here and dictate that when there are no records returned, there surely cannot be a starting cursor and ending cursor. I know that if the cursor was an index, then one could use int.MinValue
and int.MaxValue
-- but it is not. For example, if the cursor on an item is an ID field of type Guid, there is no possible guid that could represent the starting cursor or ending cursor for a connection that returned no results. So I think it is clear that these fields must be nullable.
If we assume that startCursor and endCursor must be nullable, then we have two options before us:
- Use common sense and specify the cursor field's type of an edge type to be a non-null string value.
- Match the cursor field's type of the edge type to be nullable to match the startCursor and endCursor field types.
Let us also consider one final thing: how does typical executing code use these fields? Well, it would store the startCursor or endCursor fields verbatim within a variable until needed to pass to the 'after' or 'before' property of another connection request. No parsing or any other type of processing should take place. So in this instance, 'after' or 'before' can be nullable, and indeed would always return the first page of a list if a user tried to navigate forward or backward from a connection that returned no results with null startCursor and endCursor fields. This seems to be perfectly logical behavior.
I suggest implementing the changes shown here, where the edge type's cursor field is non-nullable, but the pageinfo's startCursor and endCursor fields are nullable.
@@ -34,11 +34,11 @@ public ConnectionType() | |||
.Name("pageInfo") | |||
.Description("Information to aid in pagination."); | |||
|
|||
Field<ListGraphType<TEdgeType>>() | |||
Field<NonNullGraphType<ListGraphType<TEdgeType>>>() |
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.
👍
.Name("edges") | ||
.Description("A list of all of the edges returned in the connection."); | ||
|
||
Field<ListGraphType<TNodeType>>() | ||
Field<NonNullGraphType<ListGraphType<TNodeType>>>() |
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.
👍
@SimonCropp I do think this is ready to go but I might release another v4 before v5, in which case we shouldn't merge into master yet. I'll try to review again this weekend. |
Hi @SimonCropp, why was revert NonNullGraphType<TConnectionType this revert performed? It seems to me that the connection itself should still be non-nullable. |
@JTeeuwissen this wasnt merged |
thoughts on this one?