diff --git a/CHANGELOG.md b/CHANGELOG.md index 2365243049a..7b0d70cf43c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## Apollo Client 3.3.6 + +### Bug Fixes + +- Immediately apply `queryType: true`, `mutationType: true`, and `subscriptionType: true` type policies, rather than waiting for the first time the policy is used, fixing a [regression](https://github.com/apollographql/apollo-client/issues/7443) introduced by [#7065](https://github.com/apollographql/apollo-client/pull/7065).
+ [@benjamn](https://github.com/benjamn) in [#7463](https://github.com/apollographql/apollo-client/pull/7463) + ## Apollo Client 3.3.5 ### Improvements diff --git a/src/cache/inmemory/__tests__/policies.ts b/src/cache/inmemory/__tests__/policies.ts index 452a6c377f7..86315bbc84f 100644 --- a/src/cache/inmemory/__tests__/policies.ts +++ b/src/cache/inmemory/__tests__/policies.ts @@ -4872,6 +4872,12 @@ describe("type policies", function () { } }); + expect(cache.readQuery({ + query: gql`query { __typename }`, + })).toEqual({ + __typename: "RootQuery", + }); + const ALL_ITEMS = gql` query Items { __typename @@ -4921,4 +4927,48 @@ describe("type policies", function () { ], }); }); + + it("can configure {query,mutation,subscription}Type:true", () => { + const cache = new InMemoryCache({ + typePolicies: { + RootQuery: { + queryType: true, + }, + RootMutation: { + mutationType: true, + }, + RootSubscription: { + subscriptionType: true, + }, + } + }); + + expect(cache.readQuery({ + query: gql`query { __typename }`, + })).toEqual({ + __typename: "RootQuery", + }); + + expect(cache.readFragment({ + id: "ROOT_MUTATION", + fragment: gql` + fragment MutationTypename on RootMutation { + __typename + } + `, + })).toEqual({ + __typename: "RootMutation", + }); + + expect(cache.readFragment({ + id: "ROOT_SUBSCRIPTION", + fragment: gql` + fragment SubscriptionTypename on RootSubscription { + __typename + } + `, + })).toEqual({ + __typename: "RootSubscription", + }); + }); }); diff --git a/src/cache/inmemory/policies.ts b/src/cache/inmemory/policies.ts index dd9e0eef8ea..58db0bdf96f 100644 --- a/src/cache/inmemory/policies.ts +++ b/src/cache/inmemory/policies.ts @@ -358,7 +358,31 @@ export class Policies { public addTypePolicies(typePolicies: TypePolicies) { Object.keys(typePolicies).forEach(typename => { - const incoming = typePolicies[typename]; + const { + queryType, + mutationType, + subscriptionType, + ...incoming + } = typePolicies[typename]; + + // Though {query,mutation,subscription}Type configurations are rare, + // it's important to call setRootTypename as early as possible, + // since these configurations should apply consistently for the + // entire lifetime of the cache. Also, since only one __typename can + // qualify as one of these root types, these three properties cannot + // be inherited, unlike the rest of the incoming properties. That + // restriction is convenient, because the purpose of this.toBeAdded + // is to delay the processing of type/field policies until the first + // time they're used, allowing policies to be added in any order as + // long as all relevant policies (including policies for supertypes) + // have been added by the time a given policy is used for the first + // time. In other words, since inheritance doesn't matter for these + // properties, there's also no need to delay their processing using + // the this.toBeAdded queue. + if (queryType) this.setRootTypename("Query", typename); + if (mutationType) this.setRootTypename("Mutation", typename); + if (subscriptionType) this.setRootTypename("Subscription", typename); + if (hasOwn.call(this.toBeAdded, typename)) { this.toBeAdded[typename].push(incoming); } else { @@ -390,10 +414,6 @@ export class Policies { // using field policies to merge child objects. setMerge(existing, incoming.merge); - if (incoming.queryType) this.setRootTypename("Query", typename); - if (incoming.mutationType) this.setRootTypename("Mutation", typename); - if (incoming.subscriptionType) this.setRootTypename("Subscription", typename); - existing.keyFn = // Pass false to disable normalization for this typename. keyFields === false ? nullKeyFieldsFn :