-
Notifications
You must be signed in to change notification settings - Fork 114
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
If requested, validate binding-types get the right fields #70
Conversation
One sharp edge of the new `bindings` setting (when used for composite types) is this: the (presumably struct) type to which you're binding may expect to have particular fields, but it's GraphQL so you could have requested some other set of fields. Now, if you ask us, we check. Specifically, I've added a new setting under the `bindings` items, which says: everywhere we query this must select these fields. (Or use its own inline `# @genqlient(bind: ...)`.) It must select exactly those fields, in order, no more, no less. This was fairly easy to implement; actually comparing the selections was surprisingly much code but it's all pretty straightforward. Test plan: make check Reviewers: csilvers, marksandstrom, miguel, adam
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.
The implementation looks straight forward. 👍
I was wondering if json.Decoder with DisallowUnknownFields set could work for this. The validation wouldn't be as strong, but maybe it would be good enough? (Also, the expectation for UnmarshalJSON would be that the mention returns an error if the value is somehow incompatible.)
I think it's better for us to validate, because we can do it at compile-time. DisallowUnknownFields might be a good idea, although I worry that some GraphQL server will be badly-behaved and it will do more harm than good. |
In this commit I add two related features to genqlient: conflict-detection to avoid generating two distinct types with the same name, and an option to specify the type-name genqlient should use for some type. The conflict-detection was pretty simple once I realized I had already written all the code to do it in #70. There was a bunch of wiring, since we now need to keep track of the GraphQL type/selection-set that each type corresponds to, but it was pretty straightforward. This allows us to: - detect and reject if you have really sneaky type-names (there are some examples documented in `names.go`) - more clearly crash if genqlient accidentally generates two conflicting types, and - avoid stack-overflow when handing recursive (input) types (although sadly the poor support for options on input types (#14) makes them difficult to use in many cases; you really need to be able to set `pointer: true`) And with that all set up, the type-naming was also easy! (It doesn't have to get into the core of the type-generator, just plug in where we choose names. The desire for conflict detection was the main reason I hadn't set it up already.) Note that the existing limitation of #70 that the fields have to be in exactly the same order remains (and is now documented as #93); it's not deeply hard to fix but it's surprisingly much work. Issue: #60 Issue: #12 Test plan: make check Reviewers: csilvers, marksandstrom, adam, miguel, jvoll, mahtab
In this commit I add two related features to genqlient: conflict-detection to avoid generating two distinct types with the same name, and an option to specify the type-name genqlient should use for some type. The conflict-detection was pretty simple once I realized I had already written all the code to do it in #70. There was a bunch of wiring, since we now need to keep track of the GraphQL type/selection-set that each type corresponds to, but it was pretty straightforward. This allows us to: - detect and reject if you have really sneaky type-names (there are some examples documented in `names.go`) - more clearly crash if genqlient accidentally generates two conflicting types, and - avoid stack-overflow when handing recursive (input) types (although sadly the poor support for options on input types (#14) makes them difficult to use in many cases; you really need to be able to set `pointer: true`) And with that all set up, the type-naming was also easy! (It doesn't have to get into the core of the type-generator, just plug in where we choose names. The desire for conflict detection was the main reason I hadn't set it up already.) Note that the existing limitation of #70 that the fields have to be in exactly the same order remains (and is now documented as #93); it's not deeply hard to fix but it's surprisingly much work. Issue: #60 Issue: #12 Test plan: make check Reviewers: csilvers, marksandstrom, adam, miguel, jvoll, mahtab
## Summary: In this commit I add two related features to genqlient: conflict-detection to avoid generating two distinct types with the same name, and an option to specify the type-name genqlient should use for some type. The conflict-detection was pretty simple once I realized I had already written all the code to do it in #70. There was a bunch of wiring, since we now need to keep track of the GraphQL type/selection-set that each type corresponds to, but it was pretty straightforward. This allows us to: - detect and reject if you have really sneaky type-names (there are some examples documented in `names.go`) - more clearly crash if genqlient accidentally generates two conflicting types, and - avoid stack-overflow when handing recursive (input) types (although sadly the poor support for options on input types (#14) makes them difficult to use in many cases; you really need to be able to set `pointer: true`) And with that all set up, the type-naming was also easy! (It doesn't have to get into the core of the type-generator, just plug in where we choose names. The desire for conflict detection was the main reason I hadn't set it up already.) Note that the existing limitation of #70 that the fields have to be in exactly the same order remains (and is now documented as #93); it's not deeply hard to fix but it's surprisingly much work. Issue: #60 Issue: #12 ## Test plan: make check Author: benjaminjkraft Reviewers: StevenACoffman, jvoll, benjaminjkraft, aberkan, csilvers, dnerdy, mahtabsabet, MiguelCastillo Required Reviewers: Approved By: StevenACoffman, jvoll Checks: ✅ Test (1.17), ✅ Test (1.16), ✅ Test (1.15), ✅ Test (1.14), ✅ Lint, ✅ Test (1.17), ✅ Test (1.16), ✅ Test (1.15), ✅ Test (1.14), ✅ Lint Pull Request URL: #94
Summary:
One sharp edge of the new
bindings
setting (when used for compositetypes) is this: the (presumably struct) type to which you're binding
may expect to have particular fields, but it's GraphQL so you could have
requested some other set of fields. Now, if you ask us, we check.
Specifically, I've added a new setting under the
bindings
items, whichsays: everywhere we query this must select these fields. (Or use its
own inline
# @genqlient(bind: ...)
.) It must select exactly thosefields, in order, no more, no less. This was fairly easy to implement;
actually comparing the selections was surprisingly much code but it's
all pretty straightforward.
Test plan:
make check