-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Fix type policy inheritance involving fuzzy possibleTypes
#10633
Fix type policy inheritance involving fuzzy possibleTypes
#10633
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
const cache = new InMemoryCache({ | ||
possibleTypes: { | ||
EntitySupertype: [".*Entity"], | ||
}, | ||
typePolicies: { | ||
Query: { | ||
fields: { | ||
coworkers: { | ||
merge(existing, incoming) { | ||
return existing ? existing.concat(incoming) : incoming; | ||
}, | ||
}, | ||
}, | ||
}, | ||
|
||
// The point of this test is to ensure keyFields: ["uid"] can be | ||
// registered for all __typename strings matching the RegExp /.*Entity/, | ||
// without manually enumerating all of them. | ||
EntitySupertype: { | ||
keyFields: ["uid"], | ||
}, | ||
}, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although this may still look like a lot of boilerplate, the key point is that we don't need any mention of subtypes like CoworkerEntity
or ManagerEntity
in this configuration code.
data: { | ||
coworkers: [ | ||
{ __typename: "CoworkerEntity", uid: "qwer", name: "Alessia" }, | ||
{ __typename: "CoworkerEntity", uid: "asdf", name: "Jerel" }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm honored to make it into a test 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TIL you can use fuzzy type names for possibleTypes
. I'd love if we could add some documentation around that behavior at some point.
Nice work!
777623f
to
f9ab7a2
Compare
This looks like a very useful pattern - we should definitely get that into the docs! |
Very cool! +1 on getting that pattern into the docs, created an issue here: #10639 |
In #10599 I suggested two typical/supported ways of configuring entity identification:
keyFields: [...]
(preferred,__typename
-specific) and defining adataIdFromObject
function (legacy, catch-all).Unless you can enforce a blanket assumption that all your types must have a single
id
field (unlikely, brittle), both approaches ultimately require listing the__typename
s of all the types whosekeyFields
you want to configure, which can be annoying if your application uses many different entity types.The good news: I think I've found a way to combine a few different
InMemoryCache
features to achieve a blanketkeyFields
policy without enumerating all the relevant__typename
strings. This approach combines the following features:EntitySupertype
below) to define a singlekeyFields: ["uid"]
configuration that subtypes can either inherit or override with their own definitions, according topossibleTypes
.possibleTypes
(Bring back heuristic fragment matching, with a twist. #6901) are capable of defining supertype-subtype relationships based onRegExp
patterns in the subtype name strings (such asEntitySupertype: [".*Entity"]
below), so the subtype strings are not required to match any known__typename
exactly.With these two existing features combined,
EntitySupertype
can definekeyFields: ["uid"]
just once (usinguid
instead ofid
here to make sure we aren't accidentally relying on defaultid
behavior), and then any__typename
that ends withEntity
should automatically inherit that samekeyFields
configuration, even if the type has no other type/field policies defined.Note that
EntitySupertype
is a made-up client-side type, and does not necessarily need to exist in your schema, though if you already have a common supertype that would work (likeNode
), I would recommend reusing that existing type instead of making up a new one.Picking
".*Entity"
as a naming convention is obviously an opinionated choice, not appropriate for all schemas and types, but you can use several different patterns, as well as exact__typename
strings, so hopefully there's enough flexibility here to makeEntitySupertype
cover all/most of your entity types.The bad news: this story was slightly broken, since it implicitly required subtypes to have some type/field policy configuration in order to be capable of inheriting from
EntitySupertype
. You could go through and add empty type policies for the relevant subtypes, but that brings back the chore of manually enumerating all relevant__typename
strings.Neither of these
InMemoryCache
features is new, and both are definitely on the obscure side, but it's important to me to keep all existing features working as intended (unless we decide to remove them in a major version), no matter how obscure they may be.