Preserve @deprecated when reason = null#4006
Preserve @deprecated when reason = null#4006captbaritone wants to merge 1 commit intographql:nextfrom
Conversation
✅ Deploy Preview for compassionate-pike-271cb3 ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
|
Here's a minimal repro of the issue: import { printSchema, buildSchema } from "graphql";
const SDL = `
type Query {
hello: String @deprecated(reason: null)
}`;
console.log(printSchema(buildSchema(SDL)));
/* Outputs:
type Query {
hello: String
}
*/ |
There was a problem hiding this comment.
This looks like a valid change to me as the value is explicitly set to be nullable, and is hinted at at in the description that the reason is usually there
graphql-js/src/type/directives.ts
Lines 224 to 231 in 9c90a23
|
My guess is that this is an artifact from the fact that originally explicit nulls were not allowed (or possibly the default superceded them?) -- I am not personally aware of the history, just reading a bit from graphql/graphql-spec#418 -- and that when those changes were made, the directive definition should have been updated from: directive @deprecated(
reason: String = "No longer supported"
) on FIELD_DEFINITION | ENUM_VALUEto directive @deprecated(
reason: String! = "No longer supported"
) on FIELD_DEFINITION | ENUM_VALUEI do wonder then whether a "bug fix" should be issued here in terms of the implementation or in terms of the spec. [Reminds me of https://github.com//pull/3859] My guess is that the best course of action is to bring this up at a WG meeting! Nice find! |
benjie
left a comment
There was a problem hiding this comment.
We should make this argument non-nullable in the spec. Nevertheless, I approve of this change.
|
Thanks for bringing this up. Looks like in terms of the solution, this was superseded by: Closing, feel free to reopen if I've misunderstood or there is more to discuss! |
I noticed an issue where creating a
GraphQLSchemafrom an SDL and then printing it again results in dropping a@deprecateddirective if the reason is explicitly set tonull.In
GraphQLSchemawe don't store the existence of a deprecated directive and its reason separately. We simply store thedeprecatedReason. Becausereasonhas a default, this is mostly fine since even if you don't provide a reason string, you still end up with one. However, the oddities of defaults in GraphQL means that you can pass an explicitnullas your reason.In this case you end up with
deprecatedReason: nullin yourGraphQLSchemawhich we currently treat as the same asundefinedwhen printing, meaning the@deprecated(reason: null)gets dropped.I open this PR mostly to raise this issue rather than to advocate for this specific solution. I recognize that interfaces like
GraphQLFieldConfigare part of the public API, and thus this might mean the change is technically a breaking change, since there are likely places where people assumed they could setdeprecatedReason: nullto indicate the field was not deprecated.Another (even more breaking) option would be to decide that the reason argument to
@deprecatedshould be non-optional, and thus allow us to always assume that every deprecated field has a non-nullable reason.