-
Notifications
You must be signed in to change notification settings - Fork 2k
GraphQLSchema => IntrospectionSchema utility #1114
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
Conversation
@mjmahone You don't need import {execute, parse, getIntrospectionQuery} from 'graphql-js';
const introspection = await execute({
schema,
document: parse(getIntrospectionQuery()),
}); The only one problem I see with this approach is that it's async so you need to deal with promise 😞 |
@IvanGoncharov I do think it would be good to make clear that this is not meant to be used as part of the GraphQL server execution context, though. |
…nFromSchema. This has the advantage of making clear the conversion is NOT meant to be used within a server Query context
I agree with @IvanGoncharov - introspection is designed to be collected via execution. The GraphQL execution is lightweight and general purpose for exactly this reason. I don't think the query depth or null fields are weird, they're part of the definition of introspection. This feels like premature optimization to me, what do we gain that we didn't have before? |
Right now this is just API simplification. If gaining sync execution is valuable, then we could enable that for all synchronously executable services by having execute not wrap executeOperation in a Promise wrapper. I'd prefer that approach if this is the primary reason for the PR |
For the "cleaning" utility - could this be a simpler general purpose utility that just deletes fields with I'm not totally sure what the purpose of this cleaning is since we're typically not calling If having exact types is the intent, then we could make the existing introspection flow types exact by including the fact that the unrelated fields of |
Sync execution is very valuable on its own, it will help a lot with GraphQL adoption for many scenarios beyond classic client-server APIs, e.g. graphql-sync. If it falls outside of scope for this PR it would be great to have a separate issue for it to encourage community contribution. |
@leebyron there was no way to run the test for this correctly against the async/execute query without doing the cleaning: chai doesn't have a comparison that is It's not good enough to just clean up |
I'm not going to figure out how to get sync execution working, and I need this internally to use with the next release. So I guess I can close this and just pull the code to be internal-to-facebook instead. The primary reason for this was to provide a standard "convert from one to the other" API (i.e. something like |
#1115 adds a sync path for execution - @IvanGoncharov I'd like your opinion of if this will cover the more general cases you've encountered. |
If the only use case is for writing better tests, then there are other more simple avenues we could take. For example, this codebase uses |
That is the specified definition of introspection. If we'd like a nominally easier to understand API, we can certainly add that, but it should be a one-liner implemented using exactly that line of code. I think #1115 could help make that easier by guaranteeing a sync result and at least avoiding async when it's not necessary |
Yup, this probably isn't useful for now. |
The IntrospectionSchema is a useful type for doing things like comparing two versions of the same schema. In order to use it efficiently, this adds a utility for converting from a regular GraphQLSchema directly to an IntrospectionQuery or IntrospectionSchema.
In order to test this effectively against the existing corpus of GraphQLSchema => Introspection, I've also added a utility that takes a raw IntrospectionQuery response, and "cleans it up". This cleaning is necessary, as the response from the server includes fields that aren't explicitly specified in
IntrospectionQuery
's type system (these fields are alwaysnull
, such as theinterfaces
field on types of kindUNION
). Furthermore, the response from the server may not include all fields that are specified in the type system. While these fields aren't, strictly speaking, required, it is much easier to work with a fully-and-exactly typed object. Both for tests (where we can useexpect().to.deeply.equal()
instead of coming up with our own equality matcher) and for general-purpose algorithms and debugging (having many guaranteed-null fields printed in a debugger can cause confusion).