@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.1",
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.1",
29
- "@apollo/federation-internals": "2.4.1",
30
- "@apollo/query-planner": "2.4.1",
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', () => {