@apollo/gateway 2.4.1 → 2.4.2
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apollo/gateway",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.2",
|
|
4
4
|
"description": "Apollo Gateway",
|
|
5
5
|
"author": "Apollo <packages@apollographql.com>",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@apollo/composition": "2.4.
|
|
29
|
-
"@apollo/federation-internals": "2.4.
|
|
30
|
-
"@apollo/query-planner": "2.4.
|
|
28
|
+
"@apollo/composition": "2.4.2",
|
|
29
|
+
"@apollo/federation-internals": "2.4.2",
|
|
30
|
+
"@apollo/query-planner": "2.4.2",
|
|
31
31
|
"@apollo/server-gateway-interface": "^1.1.0",
|
|
32
32
|
"@apollo/usage-reporting-protobuf": "^4.1.0",
|
|
33
33
|
"@apollo/utils.createhash": "^2.0.0",
|
|
@@ -4863,6 +4863,251 @@ describe('executeQueryPlan', () => {
|
|
|
4863
4863
|
}
|
|
4864
4864
|
`);
|
|
4865
4865
|
});
|
|
4866
|
+
|
|
4867
|
+
test('handles @requires on @interfaceObject that applies to only one of the queried implementation', async () => {
|
|
4868
|
+
// The case this test is that where the @interfaceObject in s2 has a @requires, but the query we send requests the field on which
|
|
4869
|
+
// there is this @require only for one of the implementation type, which it request another field with no require for another implementation.
|
|
4870
|
+
// And we're making sure the requirements only get queried for T1, the first type.
|
|
4871
|
+
const s1 = {
|
|
4872
|
+
name: 's1',
|
|
4873
|
+
typeDefs: gql`
|
|
4874
|
+
extend schema
|
|
4875
|
+
@link(url: "https://specs.apollo.dev/federation/v2.4", import: ["@key"])
|
|
4876
|
+
|
|
4877
|
+
type Query {
|
|
4878
|
+
is: [I!]!
|
|
4879
|
+
}
|
|
4880
|
+
|
|
4881
|
+
interface I @key(fields: "id") {
|
|
4882
|
+
id: ID!
|
|
4883
|
+
name: String
|
|
4884
|
+
req: Req
|
|
4885
|
+
}
|
|
4886
|
+
|
|
4887
|
+
type T1 implements I @key(fields: "id") {
|
|
4888
|
+
id: ID!
|
|
4889
|
+
name: String
|
|
4890
|
+
req: Req
|
|
4891
|
+
}
|
|
4892
|
+
|
|
4893
|
+
type T2 implements I @key(fields: "id") {
|
|
4894
|
+
id: ID!
|
|
4895
|
+
name: String
|
|
4896
|
+
req: Req
|
|
4897
|
+
}
|
|
4898
|
+
|
|
4899
|
+
type Req {
|
|
4900
|
+
id: ID!
|
|
4901
|
+
}
|
|
4902
|
+
`,
|
|
4903
|
+
resolvers: {
|
|
4904
|
+
Query: {
|
|
4905
|
+
is: () => [
|
|
4906
|
+
{ __typename: 'T1', id: '2', name: 'e2', req: { id: 'r1'} },
|
|
4907
|
+
{ __typename: 'T2', id: '4', name: 'e4', req: { id: 'r2'} },
|
|
4908
|
+
{ __typename: 'T1', id: '1', name: 'e1', req: { id: 'r3'} }
|
|
4909
|
+
]
|
|
4910
|
+
},
|
|
4911
|
+
}
|
|
4912
|
+
}
|
|
4913
|
+
|
|
4914
|
+
const s2 = {
|
|
4915
|
+
name: 's2',
|
|
4916
|
+
typeDefs: gql`
|
|
4917
|
+
extend schema
|
|
4918
|
+
@link(url: "https://specs.apollo.dev/federation/v2.4", import: ["@key", "@interfaceObject", "@external", "@requires"])
|
|
4919
|
+
|
|
4920
|
+
type I @key(fields: "id") @interfaceObject {
|
|
4921
|
+
id: ID!
|
|
4922
|
+
req: Req @external
|
|
4923
|
+
v: String! @requires(fields: "req { id }")
|
|
4924
|
+
}
|
|
4925
|
+
|
|
4926
|
+
type Req {
|
|
4927
|
+
id: ID! @external
|
|
4928
|
+
}
|
|
4929
|
+
`,
|
|
4930
|
+
resolvers: {
|
|
4931
|
+
I: {
|
|
4932
|
+
__resolveReference(ref: any) {
|
|
4933
|
+
return {
|
|
4934
|
+
...ref,
|
|
4935
|
+
v: `req=${ref.req.id}`
|
|
4936
|
+
};
|
|
4937
|
+
},
|
|
4938
|
+
}
|
|
4939
|
+
}
|
|
4940
|
+
}
|
|
4941
|
+
|
|
4942
|
+
const { serviceMap, schema, queryPlanner} = getFederatedTestingSchema([ s1, s2 ]);
|
|
4943
|
+
|
|
4944
|
+
let operation = parseOp(`
|
|
4945
|
+
{
|
|
4946
|
+
is {
|
|
4947
|
+
... on T1 {
|
|
4948
|
+
v
|
|
4949
|
+
}
|
|
4950
|
+
... on T2 {
|
|
4951
|
+
name
|
|
4952
|
+
}
|
|
4953
|
+
}
|
|
4954
|
+
}
|
|
4955
|
+
`, schema);
|
|
4956
|
+
|
|
4957
|
+
let queryPlan = buildPlan(operation, queryPlanner);
|
|
4958
|
+
expect(queryPlan).toMatchInlineSnapshot(`
|
|
4959
|
+
QueryPlan {
|
|
4960
|
+
Sequence {
|
|
4961
|
+
Fetch(service: "s1") {
|
|
4962
|
+
{
|
|
4963
|
+
is {
|
|
4964
|
+
__typename
|
|
4965
|
+
... on T1 {
|
|
4966
|
+
__typename
|
|
4967
|
+
id
|
|
4968
|
+
req {
|
|
4969
|
+
id
|
|
4970
|
+
}
|
|
4971
|
+
}
|
|
4972
|
+
... on T2 {
|
|
4973
|
+
name
|
|
4974
|
+
}
|
|
4975
|
+
}
|
|
4976
|
+
}
|
|
4977
|
+
},
|
|
4978
|
+
Flatten(path: "is.@") {
|
|
4979
|
+
Fetch(service: "s2") {
|
|
4980
|
+
{
|
|
4981
|
+
... on T1 {
|
|
4982
|
+
__typename
|
|
4983
|
+
id
|
|
4984
|
+
}
|
|
4985
|
+
... on I {
|
|
4986
|
+
__typename
|
|
4987
|
+
req {
|
|
4988
|
+
id
|
|
4989
|
+
}
|
|
4990
|
+
}
|
|
4991
|
+
} =>
|
|
4992
|
+
{
|
|
4993
|
+
... on I {
|
|
4994
|
+
v
|
|
4995
|
+
}
|
|
4996
|
+
}
|
|
4997
|
+
},
|
|
4998
|
+
},
|
|
4999
|
+
},
|
|
5000
|
+
}
|
|
5001
|
+
`);
|
|
5002
|
+
|
|
5003
|
+
let response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
|
|
5004
|
+
expect(response.errors).toBeUndefined();
|
|
5005
|
+
expect(response.data).toMatchInlineSnapshot(`
|
|
5006
|
+
Object {
|
|
5007
|
+
"is": Array [
|
|
5008
|
+
Object {
|
|
5009
|
+
"v": "req=r1",
|
|
5010
|
+
},
|
|
5011
|
+
Object {
|
|
5012
|
+
"name": "e4",
|
|
5013
|
+
},
|
|
5014
|
+
Object {
|
|
5015
|
+
"v": "req=r3",
|
|
5016
|
+
},
|
|
5017
|
+
],
|
|
5018
|
+
}
|
|
5019
|
+
`);
|
|
5020
|
+
|
|
5021
|
+
// Sanity checking that if we ask for `v` (the field with @requires), then everything still works.
|
|
5022
|
+
operation = parseOp(`
|
|
5023
|
+
{
|
|
5024
|
+
is {
|
|
5025
|
+
... on T1 {
|
|
5026
|
+
v
|
|
5027
|
+
}
|
|
5028
|
+
... on T2 {
|
|
5029
|
+
v
|
|
5030
|
+
name
|
|
5031
|
+
}
|
|
5032
|
+
}
|
|
5033
|
+
}
|
|
5034
|
+
`, schema);
|
|
5035
|
+
|
|
5036
|
+
global.console = require('console');
|
|
5037
|
+
queryPlan = buildPlan(operation, queryPlanner);
|
|
5038
|
+
expect(queryPlan).toMatchInlineSnapshot(`
|
|
5039
|
+
QueryPlan {
|
|
5040
|
+
Sequence {
|
|
5041
|
+
Fetch(service: "s1") {
|
|
5042
|
+
{
|
|
5043
|
+
is {
|
|
5044
|
+
__typename
|
|
5045
|
+
... on T1 {
|
|
5046
|
+
__typename
|
|
5047
|
+
id
|
|
5048
|
+
req {
|
|
5049
|
+
id
|
|
5050
|
+
}
|
|
5051
|
+
}
|
|
5052
|
+
... on T2 {
|
|
5053
|
+
__typename
|
|
5054
|
+
id
|
|
5055
|
+
req {
|
|
5056
|
+
id
|
|
5057
|
+
}
|
|
5058
|
+
name
|
|
5059
|
+
}
|
|
5060
|
+
}
|
|
5061
|
+
}
|
|
5062
|
+
},
|
|
5063
|
+
Flatten(path: "is.@") {
|
|
5064
|
+
Fetch(service: "s2") {
|
|
5065
|
+
{
|
|
5066
|
+
... on T1 {
|
|
5067
|
+
__typename
|
|
5068
|
+
id
|
|
5069
|
+
}
|
|
5070
|
+
... on I {
|
|
5071
|
+
__typename
|
|
5072
|
+
req {
|
|
5073
|
+
id
|
|
5074
|
+
}
|
|
5075
|
+
}
|
|
5076
|
+
... on T2 {
|
|
5077
|
+
__typename
|
|
5078
|
+
id
|
|
5079
|
+
}
|
|
5080
|
+
} =>
|
|
5081
|
+
{
|
|
5082
|
+
... on I {
|
|
5083
|
+
v
|
|
5084
|
+
}
|
|
5085
|
+
}
|
|
5086
|
+
},
|
|
5087
|
+
},
|
|
5088
|
+
},
|
|
5089
|
+
}
|
|
5090
|
+
`);
|
|
5091
|
+
|
|
5092
|
+
response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
|
|
5093
|
+
expect(response.errors).toBeUndefined();
|
|
5094
|
+
expect(response.data).toMatchInlineSnapshot(`
|
|
5095
|
+
Object {
|
|
5096
|
+
"is": Array [
|
|
5097
|
+
Object {
|
|
5098
|
+
"v": "req=r1",
|
|
5099
|
+
},
|
|
5100
|
+
Object {
|
|
5101
|
+
"name": "e4",
|
|
5102
|
+
"v": "req=r2",
|
|
5103
|
+
},
|
|
5104
|
+
Object {
|
|
5105
|
+
"v": "req=r3",
|
|
5106
|
+
},
|
|
5107
|
+
],
|
|
5108
|
+
}
|
|
5109
|
+
`);
|
|
5110
|
+
});
|
|
4866
5111
|
});
|
|
4867
5112
|
|
|
4868
5113
|
describe('fields with conflicting types needing aliasing', () => {
|