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

WrapQuery transform should support multiple selections in top-level selectionSet #901

Closed
Druotic opened this issue Jul 24, 2018 · 1 comment
Labels
docs Focuses on documentation changes feature New addition or enhancement to existing solutions

Comments

@Druotic
Copy link
Contributor

Druotic commented Jul 24, 2018

Currently, the queryWrapper arg for WrapQuery is passed a SelectionSetNode and is expected to return a SelectionNode (well, the docs say any, but it gets added to the selections array here. See docs for WrapQuery here

I am proposing adding support for the query wrapper function to return either a SelectionNode or a SelectionSetNode. Only supporting SelectionNode is limiting because it means you can't expand the top level selection set of a query - i.e. only one level deep or deeper is supported. I'll provide a concrete example of what I want to accomplish to help with the explanation.

Here's a sample query taken from the testcases/docs demonstrating how it works today:

addressByUser(id: "user1") {
  streetAddress
  zip
}

Here's the associated resolver/WrapQuery usage for the addressByUser query:

            addressByUser(parent, { id }, context, info) {
              return delegateToSchema({
                schema: subSchema,
                operation: 'query',
                fieldName: 'userById',
                args: { id },
                context,
                info,
                transforms: [
                  // Wrap document takes a subtree as an AST node
                  new WrapQuery(
                    // path at which to apply wrapping and extracting
                    ['userById'],
                    (subtree: SelectionSetNode) => ({
                      // we create a wrapping AST Field
                      kind: Kind.FIELD,
                      name: {
                        kind: Kind.NAME,
                        // that field is `address`
                        value: 'address',
                      },
                      // Inside the field selection
                      selectionSet: subtree,
                    }),
                    // how to process the data result at path
                    result => result && result.address,
                  ),
                ],

And thus, the resulting downstream query looks like:

userById(id: "user1") {
  address {
    streetAddress
    zip
  }
}

Simple enough. However, imagine there were multiple fields at the top level. So, instead of userById.address.streetAddress and userById.address.zip, we had userById.addressStreetAddress and userById.addressZip. In this case, to support the same query, the downstream request would need to be changed to look something like:

userById(id: "user1") {
  addressStreetAddress
  addressZip
}

In a world where this is supported, the WrapQuery usage might look something like this:

            addressByUser(parent, { id }, context, info) {
              return delegateToSchema({
                schema: subSchema,
                operation: 'query',
                fieldName: 'userById',
                args: { id },
                context,
                info,
                transforms: [
                  new WrapQuery(
                    ['userById'],
                    (subtree: SelectionSetNode) => ({
                      kind: Kind.SELECTION_SET,
                      selectionSet: /* build selectionSet object, includes `addressStreetAddress` and `addressZip` selection/field nodes*/
                    }),
                    // how to process the data result at path
                    result => // ... do stuff with result,
                  ),
                ],
              });
            },
          },

This is a contrived example since the same could probably be accomplished with a couple of transforms/renames, but my usecase is a little more complex and this becomes a necessity. At least, I have yet to come up with a better alternative. This seems like a reasonable request.

I've made the change to graphql-tools locally and will put it up as a PR shortly. Let me know if you have any concerns with this approach.

@ghost ghost added docs Focuses on documentation changes feature New addition or enhancement to existing solutions labels Jul 24, 2018
Druotic pushed a commit to Druotic/graphql-tools that referenced this issue Jul 24, 2018
query wrapper to return selection set node.
Docs - add example where WrapQuery query wrapper
function returns a SelectionSet.
Druotic pushed a commit to Druotic/graphql-tools that referenced this issue Jul 24, 2018
Druotic pushed a commit to Druotic/graphql-tools that referenced this issue Jul 24, 2018
query wrapper to return selection set node.
Docs - add example where WrapQuery query wrapper
function returns a SelectionSet.
Druotic pushed a commit to Druotic/graphql-tools that referenced this issue Jul 24, 2018
@hwillson
Copy link
Contributor

hwillson commented Sep 7, 2018

Fixed in #902 - thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Focuses on documentation changes feature New addition or enhancement to existing solutions
Projects
None yet
Development

No branches or pull requests

2 participants