@graphql-tools/federation 4.4.6 → 4.4.7-alpha-aa1e252176385f2fde9332a8073891f0188c53b7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/dist/index.cjs +29 -10
- package/dist/index.js +29 -10
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# @graphql-tools/federation
|
|
2
2
|
|
|
3
|
+
## 4.4.7-alpha-aa1e252176385f2fde9332a8073891f0188c53b7
|
|
4
|
+
### Patch Changes
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
- [#2351](https://github.com/graphql-hive/gateway/pull/2351) [`6bd3f3b`](https://github.com/graphql-hive/gateway/commit/6bd3f3b6acefed8bac80f889b80bf80c22042abd) Thanks [@ardatan](https://github.com/ardatan)! - Fix `@provides` so the gateway only requests the provided fields the client actually selected, and stops delegating to the owner subgraph when `@provides` already covers the request.
|
|
9
|
+
|
|
10
|
+
Previously, when a subgraph declared `@provides(fields: "...")` on a field, the gateway would still:
|
|
11
|
+
|
|
12
|
+
1. Forward **every** field listed in `@provides` to that subgraph, even when the client never asked for them.
|
|
13
|
+
2. After receiving the response, plan additional delegations to the owner subgraph for `@provides`-covered fields whenever the providing subgraph declared them as `@external`, even though the data was already returned.
|
|
14
|
+
|
|
15
|
+
For example with:
|
|
16
|
+
|
|
17
|
+
```graphql
|
|
18
|
+
# subgraph B (provider)
|
|
19
|
+
type Query {
|
|
20
|
+
entity: Entity @provides(fields: "name description")
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type Entity @key(fields: "id") {
|
|
24
|
+
id: ID!
|
|
25
|
+
name: String! @external
|
|
26
|
+
description: String! @external
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
a client query of `{ entity { id name } }` would still cause the gateway to ask subgraph B for `description` *and* fetch `name` again from subgraph A (the owner of `Entity`).
|
|
31
|
+
|
|
32
|
+
After this fix:
|
|
33
|
+
|
|
34
|
+
- Only the `@provides` fields the client actually selected are forwarded to the providing subgraph (request side).
|
|
35
|
+
- The delegation planner now recognises `@provides` declarations at every nested level (e.g. `@provides(fields: "nested { nestedNested { name description } }")`) and `@provides` declarations made via inline fragments on union/interface members (e.g. `@provides(fields: "... on Book { title }")`), so the gateway no longer round-trips to the owner subgraph for fields that the providing subgraph has already returned.
|
|
36
|
+
- Fragment spreads in the client query are correctly handled when selecting `@provides`-covered fields. Previously, using a fragment spread (e.g. `...MyFrag`) to select nested `@external` fields would cause a parse error or an unnecessary delegation to the owner subgraph because the fragment body was stripped to empty by the subgraph schema filter. The gateway now inlines the provided fields directly and removes the dangling spread before forwarding the request.
|
|
37
|
+
|
|
38
|
+
Aliases, fragments, fragment spreads, `@include`/`@skip` directives wrapping a `@provides` field, and nested `@provides` selections are preserved.
|
|
39
|
+
- Updated dependencies [[`6bd3f3b`](https://github.com/graphql-hive/gateway/commit/6bd3f3b6acefed8bac80f889b80bf80c22042abd)]:
|
|
40
|
+
- @graphql-tools/delegate@12.0.18-alpha-aa1e252176385f2fde9332a8073891f0188c53b7
|
|
41
|
+
- @graphql-tools/stitch@10.1.23-alpha-aa1e252176385f2fde9332a8073891f0188c53b7
|
|
42
|
+
- @graphql-tools/wrap@11.1.17-alpha-aa1e252176385f2fde9332a8073891f0188c53b7
|
|
43
|
+
|
|
3
44
|
## 4.4.6
|
|
4
45
|
### Patch Changes
|
|
5
46
|
|
package/dist/index.cjs
CHANGED
|
@@ -713,7 +713,28 @@ function getStitchingOptionsFromSupergraphSdl(opts) {
|
|
|
713
713
|
(argumentNode) => argumentNode.name.value === "provides"
|
|
714
714
|
);
|
|
715
715
|
if (providedExtraField?.value?.kind === graphql.Kind.STRING) {
|
|
716
|
-
let
|
|
716
|
+
let registerProvidedSelectionForField2 = function(parentTypeName, fieldName, selectionSet) {
|
|
717
|
+
let fieldMap = typeNameFieldProvidedSelectionMap.get(parentTypeName);
|
|
718
|
+
if (!fieldMap) {
|
|
719
|
+
fieldMap = /* @__PURE__ */ new Map();
|
|
720
|
+
typeNameFieldProvidedSelectionMap.set(
|
|
721
|
+
parentTypeName,
|
|
722
|
+
fieldMap
|
|
723
|
+
);
|
|
724
|
+
}
|
|
725
|
+
const existing = fieldMap.get(fieldName);
|
|
726
|
+
if (existing) {
|
|
727
|
+
fieldMap.set(fieldName, {
|
|
728
|
+
kind: graphql.Kind.SELECTION_SET,
|
|
729
|
+
selections: [
|
|
730
|
+
...existing.selections,
|
|
731
|
+
...selectionSet.selections
|
|
732
|
+
]
|
|
733
|
+
});
|
|
734
|
+
} else {
|
|
735
|
+
fieldMap.set(fieldName, selectionSet);
|
|
736
|
+
}
|
|
737
|
+
}, handleSelection2 = function(fieldNodeTypeName2, selection) {
|
|
717
738
|
switch (selection.kind) {
|
|
718
739
|
case graphql.Kind.FIELD:
|
|
719
740
|
{
|
|
@@ -742,6 +763,11 @@ function getStitchingOptionsFromSupergraphSdl(opts) {
|
|
|
742
763
|
}
|
|
743
764
|
providedFields.add(selection.name.value);
|
|
744
765
|
if (selection.selectionSet) {
|
|
766
|
+
registerProvidedSelectionForField2(
|
|
767
|
+
fieldNodeTypeName2,
|
|
768
|
+
selection.name.value,
|
|
769
|
+
selection.selectionSet
|
|
770
|
+
);
|
|
745
771
|
const extraFieldNodeNamedType = getNamedTypeNode(
|
|
746
772
|
extraFieldNodeInType.type
|
|
747
773
|
);
|
|
@@ -780,15 +806,8 @@ function getStitchingOptionsFromSupergraphSdl(opts) {
|
|
|
780
806
|
typeNameFieldProvidedSelectionMap
|
|
781
807
|
);
|
|
782
808
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
fieldProvidedSelectionMap = /* @__PURE__ */ new Map();
|
|
786
|
-
typeNameFieldProvidedSelectionMap.set(
|
|
787
|
-
typeNode.name.value,
|
|
788
|
-
fieldProvidedSelectionMap
|
|
789
|
-
);
|
|
790
|
-
}
|
|
791
|
-
fieldProvidedSelectionMap.set(
|
|
809
|
+
registerProvidedSelectionForField2(
|
|
810
|
+
typeNode.name.value,
|
|
792
811
|
fieldNode.name.value,
|
|
793
812
|
providesSelectionSet
|
|
794
813
|
);
|
package/dist/index.js
CHANGED
|
@@ -711,7 +711,28 @@ function getStitchingOptionsFromSupergraphSdl(opts) {
|
|
|
711
711
|
(argumentNode) => argumentNode.name.value === "provides"
|
|
712
712
|
);
|
|
713
713
|
if (providedExtraField?.value?.kind === Kind.STRING) {
|
|
714
|
-
let
|
|
714
|
+
let registerProvidedSelectionForField2 = function(parentTypeName, fieldName, selectionSet) {
|
|
715
|
+
let fieldMap = typeNameFieldProvidedSelectionMap.get(parentTypeName);
|
|
716
|
+
if (!fieldMap) {
|
|
717
|
+
fieldMap = /* @__PURE__ */ new Map();
|
|
718
|
+
typeNameFieldProvidedSelectionMap.set(
|
|
719
|
+
parentTypeName,
|
|
720
|
+
fieldMap
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
const existing = fieldMap.get(fieldName);
|
|
724
|
+
if (existing) {
|
|
725
|
+
fieldMap.set(fieldName, {
|
|
726
|
+
kind: Kind.SELECTION_SET,
|
|
727
|
+
selections: [
|
|
728
|
+
...existing.selections,
|
|
729
|
+
...selectionSet.selections
|
|
730
|
+
]
|
|
731
|
+
});
|
|
732
|
+
} else {
|
|
733
|
+
fieldMap.set(fieldName, selectionSet);
|
|
734
|
+
}
|
|
735
|
+
}, handleSelection2 = function(fieldNodeTypeName2, selection) {
|
|
715
736
|
switch (selection.kind) {
|
|
716
737
|
case Kind.FIELD:
|
|
717
738
|
{
|
|
@@ -740,6 +761,11 @@ function getStitchingOptionsFromSupergraphSdl(opts) {
|
|
|
740
761
|
}
|
|
741
762
|
providedFields.add(selection.name.value);
|
|
742
763
|
if (selection.selectionSet) {
|
|
764
|
+
registerProvidedSelectionForField2(
|
|
765
|
+
fieldNodeTypeName2,
|
|
766
|
+
selection.name.value,
|
|
767
|
+
selection.selectionSet
|
|
768
|
+
);
|
|
743
769
|
const extraFieldNodeNamedType = getNamedTypeNode(
|
|
744
770
|
extraFieldNodeInType.type
|
|
745
771
|
);
|
|
@@ -778,15 +804,8 @@ function getStitchingOptionsFromSupergraphSdl(opts) {
|
|
|
778
804
|
typeNameFieldProvidedSelectionMap
|
|
779
805
|
);
|
|
780
806
|
}
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
fieldProvidedSelectionMap = /* @__PURE__ */ new Map();
|
|
784
|
-
typeNameFieldProvidedSelectionMap.set(
|
|
785
|
-
typeNode.name.value,
|
|
786
|
-
fieldProvidedSelectionMap
|
|
787
|
-
);
|
|
788
|
-
}
|
|
789
|
-
fieldProvidedSelectionMap.set(
|
|
807
|
+
registerProvidedSelectionForField2(
|
|
808
|
+
typeNode.name.value,
|
|
790
809
|
fieldNode.name.value,
|
|
791
810
|
providesSelectionSet
|
|
792
811
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-tools/federation",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.7-alpha-aa1e252176385f2fde9332a8073891f0188c53b7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Useful tools to create and manipulate GraphQL schemas.",
|
|
6
6
|
"repository": {
|
|
@@ -38,14 +38,14 @@
|
|
|
38
38
|
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@graphql-tools/delegate": "
|
|
41
|
+
"@graphql-tools/delegate": "12.0.18-alpha-aa1e252176385f2fde9332a8073891f0188c53b7",
|
|
42
42
|
"@graphql-tools/executor": "^1.4.13",
|
|
43
43
|
"@graphql-tools/executor-http": "^3.3.0",
|
|
44
44
|
"@graphql-tools/merge": "^9.1.5",
|
|
45
45
|
"@graphql-tools/schema": "^10.0.29",
|
|
46
|
-
"@graphql-tools/stitch": "
|
|
46
|
+
"@graphql-tools/stitch": "10.1.23-alpha-aa1e252176385f2fde9332a8073891f0188c53b7",
|
|
47
47
|
"@graphql-tools/utils": "^11.0.0",
|
|
48
|
-
"@graphql-tools/wrap": "
|
|
48
|
+
"@graphql-tools/wrap": "11.1.17-alpha-aa1e252176385f2fde9332a8073891f0188c53b7",
|
|
49
49
|
"@graphql-yoga/typed-event-target": "^3.0.2",
|
|
50
50
|
"@whatwg-node/disposablestack": "^0.0.6",
|
|
51
51
|
"@whatwg-node/events": "^0.1.2",
|