Skip to content

[RFC]: Add namedType and punctuatedName to __Type #710

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

chemisus
Copy link

Problem: There are a few issues one runs into when using the introspection of a schema to get the return types of fields.

  • nested query required for each NonNull and List means never guaranteed to get the full return type of a field on the first query
  • requires more effort than necessary to piece together the return type of a field

Example:

type StringTable {
    values: [[String!]!]!
}

As seen, StringTable is a simple container for a string[][]. The query just to find that out would look like this:

{
    __type(name:"StringTable") {
        kind
        name
        fields {
            name
            type {
                kind
                name
                ofType {
                    kind
                    name
                    ofType {
                        kind
                        name
                        ofType {
                            kind
                            name
                            ofType {
                                kind
                                name
                                ofType {
                                    kind
                                    name
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

The output of which is as follows:

{
  "data": {
    "__type": {
      "kind": "OBJECT",
      "name": "StringTable",
      "fields": [
        {
          "name": "values",
          "type": {
            "kind": "NON_NULL",
            "name": null,
            "ofType": {
              "kind": "LIST",
              "name": null,
              "ofType": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "SCALAR",
                      "name": "String"
                    }
                  }
                }
              }
            }
          }
        }
      ]
    }
  }
}

All that just for just one field is unnecessary. It's even worse when viewing several fields for several types. If there were another List added for some reason, the query would need to be modified to add another level and resent. To avoid the process of modifying and resending queries, the initial query usually includes several levels to start.

Solution: I'd like to propose adding two fields to __Type: namedType and punctuatedName.

extend type __Type {
    namedType: __Type!
    punctuatedName: String!
}

namedType returns the underlying named type, found by continually unwrapping the type until a named type is found - i.e. the type with all non-null and list wrappers removed.

punctuatedName returns the name of the (wrapped) type as it would be expressed in GraphQL's IDL; i.e. the underlying named types' name with additional punctuators from wrapping Lists and NonNulls.

Depending on the type's kind, namedType would resolve to the following:

  • Lists & NonNulls: namedType := ofType.namedType
  • All other types: namedType would yield a reference to itself.

Depending on the type's kind, punctuatedName would resolve to the following:

  • Lists: punctuatedName := '[' + ofType.punctuatedName + ']'
  • NonNulls: punctuatedName := ofType.punctuatedName + '!'
  • All other types: punctuatedName := name

Adding namedType and punctuatedName to __Type would allow for the following query:

{
    __type(name:"StringTable") {
        kind
        name
        fields {
            name
            type {
                name
                namedType {
                  kind
                  name
                }
                punctuatedName
            }
        }
    }
}

Which would yield the following output:

{
  "data": {
    "__type": {
      "kind": "OBJECT",
      "name": "StringTable",
      "fields": [
        {
          "name": "values",
          "type": {
            "name": null,
            "namedType": {
              "kind": "SCALAR",
              "name": "String"
            },
            "punctuatedName": "[[String!]!]!"
          }
        }
      ]
    }
  }
}

As seen, that is a much more compact query and response. It would also guarantee to provide a return information about the fields base type or punctuated name for any given field on the first request.

@chemisus chemisus changed the title add spec for punctuatedName and namedType #709 Proposal: Add namedType and punctuatedName to __Type Apr 17, 2020
@benjie
Copy link
Member

benjie commented Apr 17, 2020

Please change the title from Proposal: ... to [RFC] ...

@chemisus chemisus changed the title Proposal: Add namedType and punctuatedName to __Type [RFC]: Add namedType and punctuatedName to __Type Apr 17, 2020
@chemisus
Copy link
Author

@benjie If you have not yet, would you be willing to review the changes to the spec on this branch?

I've also added myself to the May 7 wg meeting graphql/graphql-wg#393

Copy link
Member

@benjie benjie 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 a great start @chemisus; I'm not actually sure how best to express this in spec-language so I've paged Ivan who may have a better idea.

@@ -348,6 +387,8 @@ Fields

* `kind` must return `__TypeKind.LIST`.
* `ofType`: Any type.
* `punctuatedName` must return `'[' + ofType.punctuatedName + ']'`.
Copy link
Member

Choose a reason for hiding this comment

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

@IvanGoncharov Using + for string concatenation in the spec is likely not allowed since it's a cross-language specification. Do we have any examples in the spec where concatenation is used that we could apply here?

Copy link
Member

Choose a reason for hiding this comment

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

Same thing goes for ofType.punctuatedName for referencing a field of a value. I think we might have to settle for writing this in prose, awkward though this may be:

Suggested change
* `punctuatedName` must return `'[' + ofType.punctuatedName + ']'`.
* `punctuatedName` must return the result of concatenating the `[` character, the wrapped type's `punctuatedName` value, and a `]` character.

@leebyron leebyron added the 💭 Strawman (RFC 0) RFC Stage 0 (See CONTRIBUTING.md) label May 7, 2020
Base automatically changed from master to main February 3, 2021 04:50
@rivantsov
Copy link
Contributor

rivantsov commented Mar 10, 2021

(not sure it is an appropriate place to add comments about the topic, still new here)

Hi everybody, I am all in favor of this addition, I think this feature is long overdue.
NGraphQL server supports similar field 'displayName',
as for need to explicitly unfold type in query (provide n level of depth), it can be solved elegantly by allowing self-referencing fragments, but it depends on deeper abilities of the server.
See both techniques in action here, in log file, at line 655, it shows request and response; TypeDetails is a self-referencing fragment:

https://github.com/rivantsov/ngraphql/blob/master/misc/UnitTestsLog.txt#L655

I would suggest to think about displayName as new field name, instead of punctuatedName, seems clearer to me, less confusing.
And of course consider allowing circular references in fragments when not on top level.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💭 Strawman (RFC 0) RFC Stage 0 (See CONTRIBUTING.md)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants