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

Improve fragment matching (resolveType) #58

Open
jonaskello opened this issue Mar 2, 2020 · 4 comments
Open

Improve fragment matching (resolveType) #58

jonaskello opened this issue Mar 2, 2020 · 4 comments

Comments

@jonaskello
Copy link
Member

Currently the default resolveType function assumes that every object has a __typename.

The only time resolveType is called is when we need to determine if a certain fragment should be applied or not. Most of the time you have a single fragment but becuase of union types you can have multiple fragments on the same object. Consider this example:

query GetBooks {
  schoolBooks {
    title
    ... on TextBook {
      classes {
        name
      }
    }
    ... on ColoringBook {
      colors {
        name
      }
    }
  }
}

Here the first fragment should be applied if the SchoolBook.__typename === "TextBook" and the second fragment if SchoolBook.__typename === "ColoringBook". In order to know this we run resolveType() and compare the __typename.

You can run into problems with denormalize if you don't have __typename everywhere (even if you had it for normalize).

Perhaps we can replace resolveType with something like shouldApplyFragment which by default returns true so all fragments are always applied. This way the simple cases with a single fragment would work without having to add __typename everywhere in the query.

@jonaskello
Copy link
Member Author

jonaskello commented Mar 2, 2020

It seems apollo has something called FragmentMatcher, and IntrospectionFragmentMatcher which seems to serve a similar purpose.

By default, Apollo Client's cache will use a heuristic fragment matcher, which assumes that a fragment matched if the result included all the fields in its selection set, and didn't match when any field was missing.

@jonaskello jonaskello changed the title Improve resolveType Improve fragment matching (resolveType) Mar 2, 2020
@jonaskello
Copy link
Member Author

Apollo seems to be moving away from fragment matcher:

https://github.com/apollographql/apollo-client/blob/379bbb024a0909714e949d76584a3b76067649cb/CHANGELOG.md

[BREAKING] FragmentMatcher, HeuristicFragmentMatcher, and IntrospectionFragmentMatcher have all been removed. We now recommend using InMemoryCache’s possibleTypes option instead. For more information see the Defining possibleTypes manually section of the docs.
@benjamn in #5073

@jonaskello
Copy link
Member Author

jonaskello commented Mar 2, 2020

This is the apollo way now:

https://www.apollographql.com/docs/react/v3.0-beta/data/fragments/#defining-possibletypes-manually

You can pass a possibleTypes option to the InMemoryCache constructor to specify supertype-subtype relationships in your schema. This object maps the name of an interface or union type (the supertype) to the types that implement or belong to it (the subtypes).

Here's an example possibleTypes declaration:

const cache = new InMemoryCache({
  possibleTypes: {
    Character: ["Jedi", "Droid"],
    Test: ["PassingTest", "FailingTest", "SkippedTest"],
    Snake: ["Viper", "Python"],
  },
});

I guess this means they always know '__typename`. Perhaps their old solution is a better fit for graphql-norm.

@jonaskello
Copy link
Member Author

This seems to be the old apollo way:

export type FragmentMatcher = (
  rootValue: any,
  typeCondition: string,
  context: any,
) => boolean;

So some kind of callback that returns a boolean seems like the way to go...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant