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

Helper + docs for selectionSet arguments #1802

Merged
merged 8 commits into from Jul 21, 2020

Conversation

gmac
Copy link
Contributor

@gmac gmac commented Jul 20, 2020

This is a followup to the work done on selectionSet arguments discussed with @yaacovCR in #1709 (comment).

This PR includes a new helper method in the stitch package called forwardArgsToSelectionSet that builds a gateway-to-subservice arguments passthrough. Implemented, it looks like this:

import { forwardArgsToSelectionSet } from '@graphql-tools/utils';

export default {
  User: {
    chirps: {
      selectionSet: forwardArgsToSelectionSet('{ chirpIds }'),
      resolve(user, args, context, info) {
        return delegateToSchema({
          schema: chirpSchema,
          operation: 'query',
          fieldName: 'chirpsById',
          args: { ids: user.chirpIds },
          context,
          info,
        });
      },
    },
  }
};

By default, forwardArgsToSelectionSet will passthrough all arguments from the gateway field to all root fields in the selection set. For advanced selection sets that request multiple fields, an additional mapping of selection names and their respective arguments may be provided:

forwardArgsToSelectionSet('{ id chirpIds }', { chirpIds: ['since'] })

This PR also contains full docs on how gateway-to-subservice argument passthroughs work, which has been a notable missing detail to date.

TODO:

  • If this PR is a new feature, reference an issue where a consensus about the design was reached (not necessary for small changes)
  • Make sure all of the significant new logic is covered by tests
  • Rebase your changes on master so that they can be merged easily
  • Make sure all tests and linter rules pass

@gmac
Copy link
Contributor Author

gmac commented Jul 20, 2020

@yaacovCR – I'm not super familiar with typescript. Can you shed some light on what I'm doing wrong with the casting of SelectionSetNode that is producing this error...? (code review suggestions welcome) thanks!

##[error]packages/utils/src/selectionSets.ts(43,10): error TS2739: Type '(field: FieldNode) => SelectionSetNode' is missing the following properties from type 'SelectionSetNode': kind, selections

Copy link
Collaborator

@yaacovCR yaacovCR left a comment

Choose a reason for hiding this comment

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

It looks like you are making a deep copy of a selection set by calling JSON stringify and parse, better might be to create a new selection set node, I use the types included within graphql-js available via my ide to figure out how to make the node I need...

@gmac gmac requested a review from yaacovCR July 21, 2020 01:54
@gmac
Copy link
Contributor Author

gmac commented Jul 21, 2020

@yaacovCR – looks like my typescript typing was way off the mark. This has been cleaned up and tests are passing; object copies no longer rely on serialization.

@yaacovCR
Copy link
Collaborator

Looks great. Thanks!

@yaacovCR
Copy link
Collaborator

Although this fits criteria for inclusion within utils as imports only graphql, seems like it is only relevant for stitching...

Might it belong within the stitch package?

I am also trying to think of a (maybe) better name for the function returning a function....

@gmac
Copy link
Contributor Author

gmac commented Jul 21, 2020 via email

@yaacovCR
Copy link
Collaborator

what about something like withGatewayFieldArguments?

Then the whole line reads selectionSet: withGatewayFieldArguments('{ theRequiredField }')

Or maybe selectionSet: passFieldArgsTo('{ theRequiredField }')

Or maybe selectionSet: forwardArgsTo('{ theRequiredField }')

@gmac
Copy link
Contributor Author

gmac commented Jul 21, 2020

I went with forwardArgsToSelectionSet – it's meaningful, and mentioning "SelectionSet" keeps the intent of the method obvious outside of just its implementation context. Moved into @graphql-tools/stitch package along with supporting tests.

I'm pretty excited about this dynamic selection set capability – it opens the door for all kinds of powerful and optimized request patterns. I've got a cross-service interface implementation that this will really optimize.

@yaacovCR
Copy link
Collaborator

These changes are great! And I agree, exciting!

I do wonder in general whether type merging might be a better overall pattern for you.

Also, if you are documentation inclined, new batch delegation option can be useful when stitching or within type merging, you may find that useful as well, but it definitely needs documentation...

@gmac
Copy link
Contributor Author

gmac commented Jul 21, 2020

sorry, just fixed a name typo in docs... that's it, I'm done here. Ready for merge whenever you are.

@gmac
Copy link
Contributor Author

gmac commented Jul 21, 2020

Also, if you are documentation inclined, new batch delegation option can be useful when stitching or within type merging, you may find that useful as well, but it definitely needs documentation...

I understand the intent of the "batching" feature – it actually sounds like something we've been doing with our own internal pattern for a while that wraps all delegateToSchema calls in a dataloader scoped by field path. I looked quickly at the PR, but I couldn't picture how it was used. If you'd draft a quick code sample demonstrating its usage, I'd be happy to write a guide (I do like writing docs). Feel free to start a discussion and ping me on it.

@yaacovCR yaacovCR merged commit ad34939 into ardatan:master Jul 21, 2020
@theguild-bot
Copy link
Collaborator

The latest changes of this PR are available as alpha in npm: 6.0.15-alpha-ad349394.0

Quickly update your package.json by running:

npx match-version @graphql-tools 6.0.15-alpha-ad349394.0

@gmac gmac deleted the gm-selection-set-args branch July 21, 2020 19:12
@ardatan ardatan added the feature New addition or enhancement to existing solutions label Jul 21, 2020
@yaacovCR
Copy link
Collaborator

@gmac sounds pretty similar, except the dataloaders are stored in a weakmap keyed by info.fieldnodes, which is unique per list, ie field path...

For some reason, tests for batch delegate are not, um, using batch delegate, https://github.com/ardatan/graphql-tools/blob/master/packages/batch-delegate/tests/typeMerging.example.test.ts
And instead mirror the non batched type merging example....

This should be fixed!

@yaacovCR
Copy link
Collaborator

Oh, I remember -- the initial version of those tests explicitly used batch delegation, but the final version just uses the key field within the merged type configuration which causes the gateway schema to automatically use batch delegation:

https://github.com/ardatan/graphql-tools/blob/master/packages/stitch/src/stitchingInfo.ts#L109-L129

Anyways, this feature needs docs. :)

@gmac
Copy link
Contributor Author

gmac commented Jul 25, 2020

@yaacovCR – looks like the website still needs a rebuild/deploy.

@yaacovCR
Copy link
Collaborator

@ardatan

@ardatan
Copy link
Owner

ardatan commented Jul 26, 2020

Fyi, Adding [deploy_website] prefix to the commit message triggers website deployment. I am doing it now :)

@yaacovCR
Copy link
Collaborator

I understand the intent of the "batching" feature – it actually sounds like something we've been doing with our own internal pattern for a while that wraps all delegateToSchema calls in a dataloader scoped by field path. I looked quickly at the PR, but I couldn't picture how it was used. If you'd draft a quick code sample demonstrating its usage, I'd be happy to write a guide (I do like writing docs). Feel free to start a discussion and ping me on it.

https://www.graphql-tools.com/docs/schema-stitching#batch-delegation

@gmac
Copy link
Contributor Author

gmac commented Jul 31, 2020

Okay, that is exactly what I was imagining; nice to see this becoming a first-class feature.

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

Successfully merging this pull request may close these issues.

None yet

4 participants