-
Notifications
You must be signed in to change notification settings - Fork 2k
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
[WIP] Add 'sortIntrospectionQuery' utility function #1185
[WIP] Add 'sortIntrospectionQuery' utility function #1185
Conversation
dummy: String | ||
} | ||
|
||
type Query implements FooA, FooB, FooC { |
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.
Should be type Query implements FooA & FooB & FooC
fixed #1179
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'm not sure how much we should value simplicity (take in $ReadOnlyArray, output $ReadOnlyArray) and DRYness vs copies with slightly more complexity. I don't think copies are very costly in this case, but I haven't benchmarked this recently so I don't really know. So all the suggestions below are just suggestions, as I think they'd make the code a little less clear in the process.
return { | ||
name: directive.name, | ||
description: directive.description, | ||
locations: sortBy(directive.locations, x => x), |
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.
there's no reason to use sortBy
here: just directive.locations.slice().sort((a, b) => a.compareLocale(b));
This is useful because then we can make sortBy
take a mutable array, and avoid one array-copy-per-sortByName
src/utilities/sortIntrospection.js
Outdated
if (!Array.isArray(array)) { | ||
throw new Error('Expected array got: ' + (array: empty)); | ||
} | ||
return array.slice().sort((obj1, obj2) => { |
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.
a bit of a nit, but we can remove this slice
with a bit of trickery. We also will no longer need the special sortBy<T>
.
function sortFields(
fields: $ReadOnlyArray<IntrospectionField>,
): $ReadOnlyArray<IntrospectionField> {
return sortByName(fields.map(field => ({
name: field.name,
description: field.description,
args: sortByName(field.args.slice()),
type: field.type,
isDeprecated: field.isDeprecated,
deprecationReason: field.deprecationReason,
}));
}
// This cannot be called on an original ReadOnly array, or it would mutate them
function sortByName<T: { +name: string }>(
array: Array<T>,
): $ReadOnlyArray<T> {
return array.sort((obj1, obj2) => obj1.name.localeCompare(obj2.name));
}
This ends up being a little more code (you now have to slice()
whenever you want to sortByName
), but now we save one array copy per field list.
src/utilities/sortIntrospection.js
Outdated
queryType: schema.queryType, | ||
mutationType: schema.mutationType, | ||
subscriptionType: schema.subscriptionType, | ||
types: sortByName(schema.types).map(sortType), |
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.
similar to below, given sortByName
now takes in a mutable array, we could save one copy here vs. the current code if we flipped this:
types: sortByName(schema.types.map(sortType)),
src/utilities/sortIntrospection.js
Outdated
mutationType: schema.mutationType, | ||
subscriptionType: schema.subscriptionType, | ||
types: sortByName(schema.types).map(sortType), | ||
directives: sortByName(schema.directives).map(sortDirective), |
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.
And the same thing here
1764f8e
to
b3da32d
Compare
b3da32d
to
032b615
Compare
@mjmahone Great suggestion 👍
What do you think? I also remembered that |
I changed my mind sorting introspection have one big disadvantage you lose a lot of data when you convert schema to introspection (resolve callback, directives, etc.). I started working on Please don't merge this PR |
Going to close this PR at your suggestion, @IvanGoncharov I agree with you that the right place for sorting is the GraphQLSchema instance itself - introspection is an intermediate representation, and since we have utilities for converting to and from introspection and schema instances, support for sorting a schema instance can be easily derived to sort any other intermediate representation, including introspection |
Based on discussion in #941 and #889
Some of GraphQL servers doesn't preserve the order of types/fields and we need to sort them to provide consistent results. I think it is the primary use case for schema sorting so it makes sense to sort the result of introspection query and it makes implementation super simple.
As for other use-cases (e.g. tests) you can query introspection with
graphqlSync
then sort it and build sorted schema usingbuildClientSchema
.