-
Notifications
You must be signed in to change notification settings - Fork 655
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
Allow @typePolicy directive on interfaces and unions #4131
Allow @typePolicy directive on interfaces and unions #4131
Conversation
👷 Deploy request for apollo-android-docs pending review.Visit the deploys page to approve it
|
apollo-ast/src/main/kotlin/com/apollographql/apollo3/ast/check_key_fields.kt
Outdated
Show resolved
Hide resolved
@@ -13,7 +13,7 @@ directive @nonnull(fields: String! = "") on OBJECT | FIELD | |||
|
|||
# Marks fields as key fields. Key fields are used to compute the cache key of an object | |||
# `keyFields` should contain a selection set. Composite fields are not supported yet. | |||
directive @typePolicy(keyFields: String!) on OBJECT | |||
directive @typePolicy(keyFields: String!) on OBJECT | INTERFACE |
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.
Do you mind adding UNION
while we're at it? They're conceptually very close to interfaces
directive @typePolicy(keyFields: String!) on OBJECT | INTERFACE | |
directive @typePolicy(keyFields: String!) on OBJECT | INTERFACE | UNION |
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.
Thank you so much for this, this is really cool! 2 small comments but look good to me overall!
@martinbonnin Where would be the best place to throw an exception, and what exception type should I use for a user facing error, i.e. ApolloException? I’ve currently added it inside schema.kt within the |
Good question. We're historically been quite liberal in what exceptions are thrown in the Gradle codegen side of things. While the runtime side of things is using That being said, For the purpose of this PR, feel free to throw
I think the best place is in |
4fb9e64
to
f28d91c
Compare
@martinbonnin Reworked it to report an issue: Had to extract out the Should also work on unions now too |
apollo-ast/src/main/kotlin/com/apollographql/apollo3/ast/internal/SchemaValidationScope.kt
Outdated
Show resolved
Hide resolved
apollo-ast/src/main/kotlin/com/apollographql/apollo3/ast/gqltypedefinition.kt
Outdated
Show resolved
Hide resolved
apollo-ast/src/main/kotlin/com/apollographql/apollo3/ast/gqltypedefinition.kt
Outdated
Show resolved
Hide resolved
f28d91c
to
7885e09
Compare
The apollo-kotlin/apollo-ast/src/main/kotlin/com/apollographql/apollo3/ast/gqltypedefinition.kt Line 101 in f28d91c
is GQLUnionTypeDefinition -> directives.toKeyFields() ?: emptySet()
- else -> error("Type '$name' cannot have key fields")
+ else -> emptySet() // If we come here, the schema is invalid and this should be caught by other validation rules |
And integration-tests had some tests using the previous logic of "overriding" the key fields. Sorry about this, things were a bit "in flight" (which is part of the reason why we disabled |
Whoops, didn’t realise the integration tests were failing. Fixing now |
Potentially stupid question: How can I run the integration tests locally? Is there a specific gradle task for them or do I need to run the |
You'll need to open the Or you can run the tests from the command line with:
|
Closes apollographql#3356 This fixes a couple of things: It changes the @typePolicy directive definition in apollo.graphqls to allow it to be used on interfaces and unions And in order for it to work on interfaces, GQLInterfaceTypeExtension has been extended to store the directives. It then validates that an object that implements an interface(s) doesn't override any key fields. This required moving the keyFields() logic out of Schema.kt and into gqltypedefinition.kt
7885e09
to
10335ad
Compare
Many thanks again for looking into this. I just pushed a small optimisation to cache the keyFields in the |
} | ||
|
||
/** | ||
* To prevent surprising behaviour, objects that declare key fields that also implement interfaces that declare key fields are an error |
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.
(Nitpick) maybe the comment could be moved to the method above.
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 added another comment on the method above and kept this one as it's the entry point of validation.
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.
🙏 👍
Thanks for the contribution! |
Hi, thanks for patching up the PR! I was able to pull it from the snapshots repository which was great, but it had some surprising behaviour with my own schema, my extend interface Node @typePolicy(keyField: "id”) And my server schema has types like this: interface Node {}
interface UniformResourceLocatable {}
# and some more interfaces etc.
type Foo implements Node, UniformResourceLocatable {} With the latest version of this PR the compiler plugin errors because
Even though Lines 206 to 216 in 2187cce
|
Oops, my bad, I forgot to exclude the 'empty' key fields special case. I'll make a patch in a few |
Fix is there, sorry for this. (the list was a list of Sets so calling distinct on it would still include the empty set) Interestingly, this does not distinguish between |
Closes #3356 (if this is the desirable behaviour!)
This fixes a couple of things:
It changes the @typePolicy directive definition in apollo.graphqls to allow it to be used on interfaces.
And in order for it to be picked up, this extends GQLInterfaceTypeExtension with a directives field.
Finally, it also checks for interfaces as well as objects when checking the key fields
@martinbonnin