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

Support for @skip and @include #275

Merged
merged 21 commits into from
Jun 21, 2016
Merged

Support for @skip and @include #275

merged 21 commits into from
Jun 21, 2016

Conversation

Poincare
Copy link
Contributor

@Poincare Poincare commented Jun 10, 2016

Implements support for @skip and @include (see #237).

TODO:

  • Update CHANGELOG.md with your change
  • 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

Field,
BooleanValue,
Variable,
} from 'graphql';
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this import all of graphql now, because the exact path isn't specified?

Copy link
Contributor

Choose a reason for hiding this comment

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

These are just the types, it doesn't actually import anything afaik

@helfer
Copy link
Contributor

helfer commented Jun 13, 2016

Quick question: would it not be possible to apply skip and include directives in a way that's as simple as the way it's done in graphql-js? That way seems pretty straight forward:

https://github.com/graphql/graphql-js/blob/1ed070fed63767e82470ca39d036539b99693c4c/src/execution/execute.js#L437

@Poincare
Copy link
Contributor Author

This implementation is pretty similar other than the fact that it allows us to easily incorporate the addition of other directives once/if the GraphQL spec adds them.

In the GraphQL AST, there is a directives on all Selection instances, meaning that it may be possible to apply directives to Selection instances rather than only Field instances. By introducing the DirectiveResolver type, we would be well-equipped to handle this and it doesn't seem to complicate the @skip and @include implementation too much, I think.

@helfer
Copy link
Contributor

helfer commented Jun 13, 2016

The thing that confuses me is that I don't know what it means to resolve a directive? Isn't that just applying a directive?

Also, I'm slightly skeptical that we can easily support other directives. So far all the directives I've seen will require somehow executing the query differently, and even returning the result differently.

Since it's not quite clear what those changes might be, it could make sense to just support skip and include in the simplest way, which is by removing nodes when the directives apply.

I'd be happy to be convinced otherwise, for instance with an example of how the current approach would easily let us support deferred and live directives.

@Poincare
Copy link
Contributor Author

DirectiveResolver seems to be poorly named. It does simply apply the directive.

I was imagining that supporting directives that actually modify the selections within a particular query (e.g. something like @add_typenames or @auth) would be very easy to implement. However, it seems that there was no intention of allowing user-defined queries according to (this)[https://github.com//pull/275] but then a PR was merged that does add custom directives to the schema. I guess it comes down to whether we think directives that modify the selections/selection sets within queries could be useful; if they aren't, I can refactor to just @skip and @include.

@stubailo
Copy link
Contributor

For context other directives we might want to support include defer and poll.

@Poincare
Copy link
Contributor Author

After discussion with @helfer, I'll go ahead an implement a shouldInclude function similar to the graphql-js implementation that will be executed inside readFromStore and writeFromStore to determine if a particular field should be expected/included.

Other directives, such as defer, poll, live, etc., will be dealt with separately, likely at the network interface level.

} = {}): ApolloStore {
const enhancers = [];

if (reportCrashes === undefined) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had to add this because otherwise one of the unit tests would print all of this useless stuff every time it ran because it irked the crash reporter.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I understand, can you show me later?

Copy link
Contributor

Choose a reason for hiding this comment

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

Use the TypeScript default argument syntax, reportCrashes = true

@Poincare Poincare changed the title First step toward supporting @skip and @include Support for @skip and @include Jun 16, 2016
@@ -120,6 +124,8 @@ export function diffSelectionSetAgainstStore({
selectionSet.selections.forEach((selection) => {
// Don't push more than one missing field per field in the query
let missingFieldPushed = false;
const included = shouldInclude(selection, variables);
Copy link
Contributor

@helfer helfer Jun 17, 2016

Choose a reason for hiding this comment

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

move this definition down to just before it is used.
and call it something other than included, maybe includeField

assert.deepEqual(query, queryClone);
});

it('throws an error on an unsupported directive', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

We don't need this, we can just ignore directives we don't know about.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As discussed, leaving this and the change below in the PR but added a note that mentions that we should move it into the validators at some point.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not so sure about this - all directives I've heard about have required the client to know about them to work - skip, defer, etc.

@helfer
Copy link
Contributor

helfer commented Jun 17, 2016

This looks good, you can merge it after some minor changes.

}): FieldDiffResult {
const storeObj = store[rootId] || {};
const storeFieldKey = storeKeyNameFromField(field, variables);
if (included === undefined) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be typeof included === 'undefined'.

Copy link
Contributor

Choose a reason for hiding this comment

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

We don't need this check at all if we use typescript default arg syntax

@@ -710,6 +718,88 @@ describe('client', () => {
});
});

describe('directives', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can move these tests to roundtrip.ts, they will be much more concise there. No need to exercise querymanager for all of them, IMO.

@stubailo stubailo merged commit 8b4ea8a into master Jun 21, 2016
@zol zol removed the in progress label Jun 21, 2016
@stubailo stubailo deleted the directives branch September 20, 2016 03:41
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 2, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants