Skip to content
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

More allowed legacy names #1235

Merged
merged 10 commits into from
Feb 14, 2018
Merged

Conversation

alloy
Copy link
Contributor

@alloy alloy commented Feb 8, 2018

Since yesterday I went back and did some more code reviewing and realised there’s another few situations where the allowed legacy names configuration isn’t being passed on, apologies for not catching that yesterday.

}

this.__allowedLegacyNames = config.allowedLegacyNames;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assumeValid configuration is about whether or not to check the configuration for common mistakes, so regardless of that the allowed legacy names still need to be stored on the schema instance.

There’s no tests for assumeValid and the below configuration being set or not, so wasn’t sure what you’d like. Should I add a test for any configuration being set, regardless of assumeValid?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a test would be great!

Let me know if I understand this correctly - you could create a GraphQLSchema with both __allowedLegacyNames and assumeValid, then extend that schema with a legacy name (which might no longer be assumed invalid), and then expect validation to pass?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I now see that validate depends on the private __validationErrors property of a schema instance.

I’m now starting to think that maybe what Relay is doing isn’t entirely correct. First it creates a schema with assumeValid set, then after extending that schema a few times it expects to still be able to validate that schema, which appears to only really be possible because extendSchema does not copy over the assumeValid configuration.

Maybe extendSchema should also copy over the assumeValid setting, but validate could accept an optional parameter to force performing the validations regardless of __validationErrors already being set?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite. extendSchema produces a new schema - while the provided schema may have been "valid" (either assumed or validated), the returned schema is different and may be invalid, so it must not copy over assumeValid or __validationErrors from the input. We would expect the extended schema to be validated by validateSchema().

Now, we may want to provide a similar assumeValid option for extendSchema, but that would be a separate thing.

validate checks __validationErrors first as a form of memoization. Since schema are considered immutable, we do not want to wastefully validate the same schema multiple times.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relay first builds a schema with the assumeValid set, because it expects that schema has been provided from a valid GraphQL server - whereas any client side extensions are within Relay's responsibility to validate

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, the GraphQLValidator second link is validating the graphql operations and fragments found within relay product code, not the schema

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I see, that makes sense. So to answer your initial question, when an original schema has __allowedLegacyNames then extending that schema should still allow those original legacy names too, regardless from whether or not they were validated on the original schema.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That validate call in GraphQLValidator is definitely still leading to an error about the legacy name in the schema . Maybe it’s just a side-effect, though, I’ll double-check that in the morrow.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably a side effect - the document validator first asserts that a valid schema if being used to validate a document. If the schema wasn't validated before that point, it will throw

* This option is provided to ease adoption and may be removed in a future
* major release.
*/
allowedLegacyNames?: ?Array<string>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be added here? If so, should the result of extendSchema include both the allowed legacy names of the input schema in addition to these?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, that seems like an excellent idea 👍

* This option is provided to ease adoption and may be removed in a future
* major release.
*/
allowedLegacyNames?: ?Array<string>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense as an alternate API for constructing a schema. 👍

@IvanGoncharov
Copy link
Member

@alloy @leebyron In theory buildClientSchema also should accept allowedLegacyNames.

Idea mode: Can we create a global array in assertValidName.js and just export addAllowedLegacyName function. We guarantee to have only one instance of graphql so you could write:

import { addAllowedLegacyName } from 'graphql';

addAllowedLegacyName('__badname');
someRelayFunctionWorkingWithSDL(`
  type Query {
     __badname: String
  }
`);

That way we minimize changes in graphql-js to one file and allow to use the relay and other 3rd-party libs without any changes.
What do you think?

@alloy
Copy link
Contributor Author

alloy commented Feb 9, 2018

@IvanGoncharov I’m personally not a big fan of singletons, but have no idea if that pattern is already being employed in this library or if that’s something that’s acceptable. Will defer to @leebyron on that.

What I did do is consolidate the schema validation options into a single type that’s shared and added the allowedLegacyNames option to buildClientSchema as well.

@alloy
Copy link
Contributor Author

alloy commented Feb 9, 2018

Oh, just remembered that I still need to add tests for the existing assumeValid behaviour. Will do that later today.

* Default: false
*/
assumeValid?: boolean,
|};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think it's better to have type Options = {| ...GraphQLSchemaValidationOptions |} even though there are no other options at the moment. It shows that options arg could be used for some other options beyond validation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, makes sense 👍

@alloy
Copy link
Contributor Author

alloy commented Feb 9, 2018

@leebyron Alright, I think I’ve addressed all feedback.

Copy link
Contributor

@leebyron leebyron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good - some smaller suggestions inline

@@ -1225,18 +1225,23 @@ describe('extendSchema', () => {
query: new GraphQLObjectType({
name: 'Query',
fields: () => ({
id: { type: GraphQLID },
__badName: { type: GraphQLString },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a new test rather than changing this existing one?

];
if (allowedLegacyNames.length === 0) {
allowedLegacyNames = null;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This merge code could be much simpler and avoid the mutable var:

const schemaAllowedLegacyNames = schema.__allowedLegacyNames
const extendAllowedLegacyNames = options && options.allowedLegacyNames
const allowedLegacyNames = 
  schemaAllowedLegacyNames && extendAllowedLegacyNames
      ? schemaAllowedLegacyNames.concat(extendAllowedLegacyNames)
      : schemaAllowedLegacyNames || extendAllowedLegacyNames

@leebyron leebyron merged commit b4f2955 into graphql:master Feb 14, 2018
const allowedLegacyNames =
schemaAllowedLegacyNames && extendAllowedLegacyNames
? schemaAllowedLegacyNames.concat(extendAllowedLegacyNames)
: schemaAllowedLegacyNames || extendAllowedLegacyNames;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants