When we see that @provides specifies an overridden field, remove it from the field selection.#3191
When we see that @provides specifies an overridden field, remove it from the field selection.#3191
@provides specifies an overridden field, remove it from the field selection.#3191Conversation
… from the field selection.
✅ Docs preview readyThe preview is ready to be viewed. View the preview File Changes 1 new, 3 changed, 0 removedBuild ID: 7df5315143f5d82fb82f9680 URL: https://www.apollographql.com/docs/deploy-preview/7df5315143f5d82fb82f9680 |
🦋 Changeset detectedLatest commit: 547a3fa The changes in this PR will be included in the next version bump. This PR includes changesets to release 7 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. |
| // now we should have a SelectionSet with an array of _selections the same length as `validSelectionsIndex` | ||
| // We should be able to filter out the ones that are invalid and we'll be left with the valid selection string | ||
| const selections = selectionSet.selections(); | ||
| assert(selections.length === validSelectionsIndex.length, 'selection parsing failed'); |
There was a problem hiding this comment.
would it be possible to have some overriddenCoordinates that are applicable to different @provides? (so there would be no field set filtering required for this @provides)
| // cannot be considered valid in the supgraph | ||
| let validSelectionsIndex: boolean[] = []; | ||
|
|
||
| const selectionSet = parseSelectionSet({ |
There was a problem hiding this comment.
Two things here:
- It looks like you're only looking for top-level fields in the
@provides, when we really want to check all the fields. @overridecan only be on (non-interface-object) object fields, and the fields being overridden, if they exist, must also be object fields (if the field doesn't exist, it can't be "effectively" implemented by an interface object either).- The effect of this is that when looking at fields
fin@provides, you want to find the possible runtime types of that field's parent typeP, and then for each such possible runtime typeT, you want to check ifT.fis inoverriddenCoordinates. It's not sufficient to just checkP.f.
- The effect of this is that when looking at fields
In terms of how to do this, I would suggest a similar approach to removeInactiveApplications(), which modifies the given directive to exclude non-external leaf fields (potentially removing the directive entirely). The gist is:
- Call
this.getFieldSet(source, sourceMeta.providesDirective()), asaddJoinField()does, to get the (string) field set given to@provides. - Call
parseSelectionSet()to parse that field set into aSelectionSet(you can usevalidate: false, since it should already be done by this point). - You'll want to create an analog to
selectsNonExternalLeafField(), e.g.selectsOverriddenField(), to check whether the@providesselection set uses an overridden field at all.- If it doesn't, then you should just return the original
@providesstring. This is in part to avoid unnecessary selection set construction, and in part to avoid unnecessary diffs in the supergraph schema.
- If it doesn't, then you should just return the original
- When it does contain an overridden field, you'll need to call an analog to
withoutNonExternalLeafFields()that removes overridden fields.- It'll help here to create an analog to
isExternalOrHasExternalImplementations()that checks whether the field (or one of its implementers) is inoverriddenCoordinates. You can call that in the analog forselectsNonExternalLeafField()as well. - Note that the behavior when an empty selection set occurs is to remove the parent selection, which should be fine. When the top-level selection set is empty, this results in the
@providesbeing effectively dropped entirely.
- It'll help here to create an analog to
| const name = this.joinSpecName(idx); | ||
|
|
||
| // fields in this subgraph that are no longer viable because they've been overridden | ||
| const overriddenFields = this.completelyOverriddenFieldMap.get(idx); |
There was a problem hiding this comment.
Note that:
- Since the result of overridden field removal may be to remove the
@providesentirely, this could result in the@join__fieldbecoming unnecessary. This means the computation of the "updated"@providesneeds to be done before that, so thatneedsJoinField()can be aware of it. (Might want to put it inFieldMergeContextProperties.) - In
@join__field, theusedOverriddenargument is set based on whether the overridden field is "used" (i.e. is in@key/@requires/@provides/@fromContextor is an object field that implements some interface field in the subgraph). If it's used, then the field still needs to be in the overridden subgraph, but otherwise (for non-progressive overrides) it is effectively dropped from supergraph schema metadata.- This definition of "used" should account for the
@provideseffectively omitting (non-progressive) overridden fields. My suggestion here is that thecollectUsedFields()function should collect two separate sets ofFieldDefinitions: one for@provides, and one for the rest. Both of these should be stored inFederationMetadata. - The
FederationMetadata.isFieldUsed()method should check both sets. You should add a new method toFederationMetadatacalled e.g.isFieldUsedIgnoringProvides()that only checks the non-@providesset. - In
validateOverride(), when computingoverriddenFieldIsReferenced, useisFieldUsedIgnoringProvides()instead ofisFieldUsed()ifoverrideLabelis unset.
- This definition of "used" should account for the
…ameter to join spec
I moved the logic that checked to ensure all
@externaldirectives were used from the subgraph validations into the merge validations. Other than that, I'm part of me is unsure about the assert inside ofremoveOverriddenFieldFromFieldSetand wants to just return undefined, but I think the test harness should catch if I've created any problems there