@apollo/gateway 2.0.0-alpha.2 → 2.0.0-alpha.6

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.
Files changed (130) hide show
  1. package/dist/config.d.ts +43 -15
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js +28 -18
  4. package/dist/config.js.map +1 -1
  5. package/dist/datasources/LocalGraphQLDataSource.js.map +1 -1
  6. package/dist/datasources/RemoteGraphQLDataSource.d.ts.map +1 -1
  7. package/dist/datasources/RemoteGraphQLDataSource.js +4 -1
  8. package/dist/datasources/RemoteGraphQLDataSource.js.map +1 -1
  9. package/dist/executeQueryPlan.d.ts.map +1 -1
  10. package/dist/executeQueryPlan.js +2 -2
  11. package/dist/executeQueryPlan.js.map +1 -1
  12. package/dist/index.d.ts +37 -22
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +199 -283
  15. package/dist/index.js.map +1 -1
  16. package/dist/schema-helper/addResolversToSchema.d.ts +4 -0
  17. package/dist/schema-helper/addResolversToSchema.d.ts.map +1 -0
  18. package/dist/schema-helper/addResolversToSchema.js +62 -0
  19. package/dist/schema-helper/addResolversToSchema.js.map +1 -0
  20. package/dist/schema-helper/error.d.ts +6 -0
  21. package/dist/schema-helper/error.d.ts.map +1 -0
  22. package/dist/schema-helper/error.js +14 -0
  23. package/dist/schema-helper/error.js.map +1 -0
  24. package/dist/schema-helper/index.d.ts +4 -0
  25. package/dist/schema-helper/index.d.ts.map +1 -0
  26. package/dist/schema-helper/index.js +16 -0
  27. package/dist/schema-helper/index.js.map +1 -0
  28. package/dist/schema-helper/resolverMap.d.ts +16 -0
  29. package/dist/schema-helper/resolverMap.d.ts.map +1 -0
  30. package/dist/schema-helper/resolverMap.js +3 -0
  31. package/dist/schema-helper/resolverMap.js.map +1 -0
  32. package/dist/supergraphManagers/IntrospectAndCompose/index.d.ts +31 -0
  33. package/dist/supergraphManagers/IntrospectAndCompose/index.d.ts.map +1 -0
  34. package/dist/supergraphManagers/IntrospectAndCompose/index.js +112 -0
  35. package/dist/supergraphManagers/IntrospectAndCompose/index.js.map +1 -0
  36. package/dist/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.d.ts +12 -0
  37. package/dist/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.d.ts.map +1 -0
  38. package/dist/{loadServicesFromRemoteEndpoint.js → supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.js} +6 -6
  39. package/dist/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.js.map +1 -0
  40. package/dist/supergraphManagers/LegacyFetcher/index.d.ts +33 -0
  41. package/dist/supergraphManagers/LegacyFetcher/index.d.ts.map +1 -0
  42. package/dist/supergraphManagers/LegacyFetcher/index.js +149 -0
  43. package/dist/supergraphManagers/LegacyFetcher/index.js.map +1 -0
  44. package/dist/supergraphManagers/LocalCompose/index.d.ts +19 -0
  45. package/dist/supergraphManagers/LocalCompose/index.d.ts.map +1 -0
  46. package/dist/supergraphManagers/LocalCompose/index.js +55 -0
  47. package/dist/supergraphManagers/LocalCompose/index.js.map +1 -0
  48. package/dist/supergraphManagers/UplinkFetcher/index.d.ts +33 -0
  49. package/dist/supergraphManagers/UplinkFetcher/index.d.ts.map +1 -0
  50. package/dist/supergraphManagers/UplinkFetcher/index.js +98 -0
  51. package/dist/supergraphManagers/UplinkFetcher/index.js.map +1 -0
  52. package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.d.ts +25 -0
  53. package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.d.ts.map +1 -0
  54. package/dist/{loadSupergraphSdlFromStorage.js → supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.js} +40 -15
  55. package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.js.map +1 -0
  56. package/dist/supergraphManagers/UplinkFetcher/outOfBandReporter.d.ts +13 -0
  57. package/dist/supergraphManagers/UplinkFetcher/outOfBandReporter.d.ts.map +1 -0
  58. package/dist/supergraphManagers/UplinkFetcher/outOfBandReporter.js +85 -0
  59. package/dist/supergraphManagers/UplinkFetcher/outOfBandReporter.js.map +1 -0
  60. package/dist/supergraphManagers/index.d.ts +6 -0
  61. package/dist/supergraphManagers/index.d.ts.map +1 -0
  62. package/dist/supergraphManagers/index.js +14 -0
  63. package/dist/supergraphManagers/index.js.map +1 -0
  64. package/dist/utilities/createHash.d.ts +2 -0
  65. package/dist/utilities/createHash.d.ts.map +1 -0
  66. package/dist/utilities/createHash.js +15 -0
  67. package/dist/utilities/createHash.js.map +1 -0
  68. package/dist/utilities/isNodeLike.d.ts +3 -0
  69. package/dist/utilities/isNodeLike.d.ts.map +1 -0
  70. package/dist/utilities/isNodeLike.js +8 -0
  71. package/dist/utilities/isNodeLike.js.map +1 -0
  72. package/package.json +9 -7
  73. package/src/__mocks__/make-fetch-happen-fetcher.ts +3 -1
  74. package/src/__tests__/build-query-plan.feature +52 -0
  75. package/src/__tests__/executeQueryPlan.test.ts +599 -1
  76. package/src/__tests__/execution-utils.ts +3 -3
  77. package/src/__tests__/gateway/buildService.test.ts +3 -3
  78. package/src/__tests__/gateway/endToEnd.test.ts +1 -1
  79. package/src/__tests__/gateway/executor.test.ts +1 -1
  80. package/src/__tests__/gateway/lifecycle-hooks.test.ts +59 -125
  81. package/src/__tests__/gateway/opentelemetry.test.ts +8 -4
  82. package/src/__tests__/gateway/queryPlanCache.test.ts +25 -12
  83. package/src/__tests__/gateway/reporting.test.ts +42 -13
  84. package/src/__tests__/gateway/supergraphSdl.test.ts +397 -0
  85. package/src/__tests__/integration/aliases.test.ts +9 -4
  86. package/src/__tests__/integration/configuration.test.ts +146 -9
  87. package/src/__tests__/integration/logger.test.ts +1 -1
  88. package/src/__tests__/integration/networkRequests.test.ts +99 -147
  89. package/src/__tests__/integration/nockMocks.ts +30 -16
  90. package/src/__tests__/nockAssertions.ts +20 -0
  91. package/src/config.ts +149 -38
  92. package/src/datasources/LocalGraphQLDataSource.ts +1 -1
  93. package/src/datasources/RemoteGraphQLDataSource.ts +8 -2
  94. package/src/datasources/__tests__/LocalGraphQLDataSource.test.ts +1 -1
  95. package/src/datasources/__tests__/RemoteGraphQLDataSource.test.ts +4 -4
  96. package/src/executeQueryPlan.ts +14 -2
  97. package/src/index.ts +325 -452
  98. package/src/schema-helper/addResolversToSchema.ts +83 -0
  99. package/src/schema-helper/error.ts +11 -0
  100. package/src/schema-helper/index.ts +3 -0
  101. package/src/schema-helper/resolverMap.ts +23 -0
  102. package/src/supergraphManagers/IntrospectAndCompose/__tests__/IntrospectAndCompose.test.ts +370 -0
  103. package/src/{__tests__ → supergraphManagers/IntrospectAndCompose/__tests__}/loadServicesFromRemoteEndpoint.test.ts +5 -5
  104. package/src/supergraphManagers/IntrospectAndCompose/__tests__/tsconfig.json +8 -0
  105. package/src/supergraphManagers/IntrospectAndCompose/index.ts +160 -0
  106. package/src/{loadServicesFromRemoteEndpoint.ts → supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.ts} +6 -6
  107. package/src/supergraphManagers/LegacyFetcher/index.ts +226 -0
  108. package/src/supergraphManagers/LocalCompose/index.ts +79 -0
  109. package/src/supergraphManagers/UplinkFetcher/__tests__/loadSupergraphSdlFromStorage.test.ts +397 -0
  110. package/src/supergraphManagers/UplinkFetcher/__tests__/tsconfig.json +8 -0
  111. package/src/supergraphManagers/UplinkFetcher/index.ts +130 -0
  112. package/src/{loadSupergraphSdlFromStorage.ts → supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.ts} +68 -17
  113. package/src/supergraphManagers/UplinkFetcher/outOfBandReporter.ts +126 -0
  114. package/src/supergraphManagers/index.ts +5 -0
  115. package/src/utilities/__tests__/cleanErrorOfInaccessibleElements.test.ts +12 -9
  116. package/src/utilities/createHash.ts +10 -0
  117. package/src/utilities/isNodeLike.ts +11 -0
  118. package/dist/loadServicesFromRemoteEndpoint.d.ts +0 -13
  119. package/dist/loadServicesFromRemoteEndpoint.d.ts.map +0 -1
  120. package/dist/loadServicesFromRemoteEndpoint.js.map +0 -1
  121. package/dist/loadSupergraphSdlFromStorage.d.ts +0 -13
  122. package/dist/loadSupergraphSdlFromStorage.d.ts.map +0 -1
  123. package/dist/loadSupergraphSdlFromStorage.js.map +0 -1
  124. package/dist/outOfBandReporter.d.ts +0 -15
  125. package/dist/outOfBandReporter.d.ts.map +0 -1
  126. package/dist/outOfBandReporter.js +0 -88
  127. package/dist/outOfBandReporter.js.map +0 -1
  128. package/src/__tests__/gateway/composedSdl.test.ts +0 -44
  129. package/src/__tests__/loadSupergraphSdlFromStorage.test.ts +0 -694
  130. package/src/outOfBandReporter.ts +0 -128
@@ -1,8 +1,10 @@
1
1
  import gql from 'graphql-tag';
2
2
  import { ApolloGateway } from '../..';
3
3
  import {
4
+ DynamicGatewayConfig,
4
5
  Experimental_DidResolveQueryPlanCallback,
5
6
  Experimental_UpdateServiceDefinitions,
7
+ ServiceDefinitionUpdate,
6
8
  } from '../../config';
7
9
  import {
8
10
  product,
@@ -11,10 +13,11 @@ import {
11
13
  accounts,
12
14
  books,
13
15
  documents,
16
+ fixtures,
17
+ fixturesWithUpdate,
14
18
  } from 'apollo-federation-integration-testsuite';
15
19
  import { Logger } from 'apollo-server-types';
16
-
17
- type GenericFunction = (...args: unknown[]) => unknown;
20
+ import resolvable from '@josephg/resolvable';
18
21
 
19
22
  // The order of this was specified to preserve existing test coverage. Typically
20
23
  // we would just import and use the `fixtures` array.
@@ -49,16 +52,14 @@ beforeEach(() => {
49
52
 
50
53
  describe('lifecycle hooks', () => {
51
54
  it('uses updateServiceDefinitions override', async () => {
52
- const experimental_updateServiceDefinitions: Experimental_UpdateServiceDefinitions = jest.fn(
53
- async () => {
55
+ const experimental_updateServiceDefinitions: Experimental_UpdateServiceDefinitions =
56
+ jest.fn(async () => {
54
57
  return { serviceDefinitions, isNewSchema: true };
55
- },
56
- );
58
+ });
57
59
 
58
60
  const gateway = new ApolloGateway({
59
61
  serviceList: serviceDefinitions,
60
62
  experimental_updateServiceDefinitions,
61
- experimental_didUpdateComposition: jest.fn(),
62
63
  logger,
63
64
  });
64
65
 
@@ -69,61 +70,7 @@ describe('lifecycle hooks', () => {
69
70
  await gateway.stop();
70
71
  });
71
72
 
72
- it('calls experimental_didFailComposition with a bad config', async () => {
73
- const experimental_didFailComposition = jest.fn();
74
-
75
- // Creating 2 subservices that clearly cannot composed.
76
- const s1 = {
77
- name: 'S1',
78
- url: 'http://S1',
79
- typeDefs: gql`
80
- type T {
81
- a: Int
82
- }
83
- `
84
- };
85
-
86
- const s2 = {
87
- name: 'S2',
88
- url: 'http://S2',
89
- typeDefs: gql`
90
- type T {
91
- a: String
92
- }
93
- `
94
- };
95
-
96
-
97
- const gateway = new ApolloGateway({
98
- async experimental_updateServiceDefinitions() {
99
- return {
100
- serviceDefinitions: [s1, s2],
101
- compositionMetadata: {
102
- formatVersion: 1,
103
- id: 'abc',
104
- implementingServiceLocations: [],
105
- schemaHash: 'abc',
106
- },
107
- isNewSchema: true,
108
- };
109
- },
110
- serviceList: [],
111
- experimental_didFailComposition,
112
- logger,
113
- });
114
-
115
- await expect(gateway.load()).rejects.toThrowError("A valid schema couldn't be composed");
116
-
117
- const callbackArgs = experimental_didFailComposition.mock.calls[0][0];
118
- expect(callbackArgs.serviceList).toHaveLength(2);
119
- expect(callbackArgs.errors[0]).toMatchInlineSnapshot(
120
- `[GraphQLError: Field "T.a" has incompatible types across subgraphs: it has type "Int" in subgraph "S1" but type "String" in subgraph "S2"]`,
121
- );
122
- expect(callbackArgs.compositionMetadata.id).toEqual('abc');
123
- expect(experimental_didFailComposition).toBeCalled();
124
- });
125
-
126
- it('calls experimental_didUpdateComposition on schema update', async () => {
73
+ it('calls experimental_didUpdateSupergraph on schema update', async () => {
127
74
  const compositionMetadata = {
128
75
  formatVersion: 1,
129
76
  id: 'abc',
@@ -131,82 +78,73 @@ describe('lifecycle hooks', () => {
131
78
  schemaHash: 'hash1',
132
79
  };
133
80
 
134
- const update: Experimental_UpdateServiceDefinitions = async () => ({
135
- serviceDefinitions,
136
- isNewSchema: true,
137
- compositionMetadata: {
138
- ...compositionMetadata,
139
- id: '123',
140
- schemaHash: 'hash2',
141
- },
142
- });
143
-
144
- // This is the simplest way I could find to achieve mocked functions that leverage our types
145
- const mockUpdate = jest.fn(update);
146
-
147
- // We want to return a different composition across two ticks, so we mock it
148
- // slightly differenty
149
- mockUpdate.mockImplementationOnce(async () => {
150
- const services = serviceDefinitions.filter(s => s.name !== 'books');
151
- return {
152
- serviceDefinitions: [
153
- ...services,
154
- {
155
- name: 'book',
156
- typeDefs: books.typeDefs,
157
- url: 'http://localhost:32542',
81
+ const mockUpdate = jest
82
+ .fn<Promise<ServiceDefinitionUpdate>, [config: DynamicGatewayConfig]>()
83
+ .mockImplementationOnce(async () => {
84
+ return {
85
+ serviceDefinitions: fixtures,
86
+ isNewSchema: true,
87
+ compositionMetadata: {
88
+ ...compositionMetadata,
89
+ id: '123',
90
+ schemaHash: 'hash2',
158
91
  },
159
- ],
160
- isNewSchema: true,
161
- compositionMetadata,
162
- };
163
- });
92
+ };
93
+ })
94
+ // We want to return a different composition across two ticks, so we mock it
95
+ // slightly differently
96
+ .mockImplementationOnce(async () => {
97
+ return {
98
+ serviceDefinitions: fixturesWithUpdate,
99
+ isNewSchema: true,
100
+ compositionMetadata,
101
+ };
102
+ });
164
103
 
165
104
  const mockDidUpdate = jest.fn();
166
105
 
167
106
  const gateway = new ApolloGateway({
168
107
  experimental_updateServiceDefinitions: mockUpdate,
169
- experimental_didUpdateComposition: mockDidUpdate,
108
+ experimental_didUpdateSupergraph: mockDidUpdate,
170
109
  logger,
171
110
  });
172
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
173
- // @ts-ignore for testing purposes, a short pollInterval is ideal so we'll override here
174
- gateway.experimental_pollInterval = 100;
111
+ // for testing purposes, a short pollInterval is ideal so we'll override here
112
+ gateway['pollIntervalInMs'] = 100;
175
113
 
176
- let resolve1: GenericFunction;
177
- let resolve2: GenericFunction;
178
- const schemaChangeBlocker1 = new Promise(res => (resolve1 = res));
179
- const schemaChangeBlocker2 = new Promise(res => (resolve2 = res));
114
+ const schemaChangeBlocker1 = resolvable();
115
+ const schemaChangeBlocker2 = resolvable();
180
116
 
181
- gateway.onSchemaChange(
117
+ gateway.onSchemaLoadOrUpdate(
182
118
  jest
183
119
  .fn()
184
- .mockImplementationOnce(() => resolve1())
185
- .mockImplementationOnce(() => resolve2()),
120
+ .mockImplementationOnce(() => schemaChangeBlocker1.resolve())
121
+ .mockImplementationOnce(() => schemaChangeBlocker2.resolve()),
186
122
  );
187
123
 
188
124
  await gateway.load();
189
125
 
190
126
  await schemaChangeBlocker1;
127
+
191
128
  expect(mockUpdate).toBeCalledTimes(1);
192
129
  expect(mockDidUpdate).toBeCalledTimes(1);
193
130
 
194
131
  await schemaChangeBlocker2;
132
+
195
133
  expect(mockUpdate).toBeCalledTimes(2);
196
134
  expect(mockDidUpdate).toBeCalledTimes(2);
197
135
 
198
136
  const [firstCall, secondCall] = mockDidUpdate.mock.calls;
199
137
 
200
- expect(firstCall[0]!.schema).toBeDefined();
201
- expect(firstCall[0].compositionMetadata!.schemaHash).toEqual('hash1');
138
+ const expectedFirstId = 'd20cfb7a9c51179aa494ed9e98153f0042892bd225437af064bf1c1aa68eab86'
139
+ expect(firstCall[0]!.compositionId).toEqual(expectedFirstId);
202
140
  // first call should have no second "previous" argument
203
141
  expect(firstCall[1]).toBeUndefined();
204
142
 
205
- expect(secondCall[0].schema).toBeDefined();
206
- expect(secondCall[0].compositionMetadata!.schemaHash).toEqual('hash2');
143
+ expect(secondCall[0]!.compositionId).toEqual(
144
+ '7dad7ab8284165a86241b8973d71f0d6ac8cb142095c717dd23443522850c225',
145
+ );
207
146
  // second call should have previous info in the second arg
208
- expect(secondCall[1]!.schema).toBeDefined();
209
- expect(secondCall[1]!.compositionMetadata!.schemaHash).toEqual('hash1');
147
+ expect(secondCall[1]!.compositionId).toEqual(expectedFirstId);
210
148
 
211
149
  await gateway.stop();
212
150
  });
@@ -231,34 +169,31 @@ describe('lifecycle hooks', () => {
231
169
  it('warns when polling on the default fetcher', async () => {
232
170
  new ApolloGateway({
233
171
  serviceList: serviceDefinitions,
234
- experimental_pollInterval: 10,
172
+ pollIntervalInMs: 10,
235
173
  logger,
236
174
  });
237
- expect(logger.warn).toHaveBeenCalledTimes(1);
238
175
  expect(logger.warn).toHaveBeenCalledWith(
239
176
  'Polling running services is dangerous and not recommended in production. Polling should only be used against a registry. If you are polling running services, use with caution.',
240
177
  );
241
178
  });
242
179
 
243
180
  it('registers schema change callbacks when experimental_pollInterval is set for unmanaged configs', async () => {
244
- const experimental_updateServiceDefinitions: Experimental_UpdateServiceDefinitions = jest.fn(
245
- async (_config) => {
181
+ const experimental_updateServiceDefinitions: Experimental_UpdateServiceDefinitions =
182
+ jest.fn(async (_config) => {
246
183
  return { serviceDefinitions, isNewSchema: true };
247
- },
248
- );
184
+ });
249
185
 
250
186
  const gateway = new ApolloGateway({
251
187
  serviceList: [{ name: 'book', url: 'http://localhost:32542' }],
252
188
  experimental_updateServiceDefinitions,
253
- experimental_pollInterval: 100,
189
+ pollIntervalInMs: 100,
254
190
  logger,
255
191
  });
256
192
 
257
- let resolve: GenericFunction;
258
- const schemaChangeBlocker = new Promise(res => (resolve = res));
259
- const schemaChangeCallback = jest.fn(() => resolve());
193
+ const schemaChangeBlocker = resolvable();
194
+ const schemaChangeCallback = jest.fn(() => schemaChangeBlocker.resolve());
260
195
 
261
- gateway.onSchemaChange(schemaChangeCallback);
196
+ gateway.onSchemaLoadOrUpdate(schemaChangeCallback);
262
197
  await gateway.load();
263
198
 
264
199
  await schemaChangeBlocker;
@@ -268,12 +203,11 @@ describe('lifecycle hooks', () => {
268
203
  });
269
204
 
270
205
  it('calls experimental_didResolveQueryPlan when executor is called', async () => {
271
- const experimental_didResolveQueryPlan: Experimental_DidResolveQueryPlanCallback = jest.fn()
206
+ const experimental_didResolveQueryPlan: Experimental_DidResolveQueryPlanCallback =
207
+ jest.fn();
272
208
 
273
209
  const gateway = new ApolloGateway({
274
- localServiceList: [
275
- books
276
- ],
210
+ localServiceList: [books],
277
211
  experimental_didResolveQueryPlan,
278
212
  });
279
213
 
@@ -283,8 +217,8 @@ describe('lifecycle hooks', () => {
283
217
  { book(isbn: "0262510871") { year } }
284
218
  `;
285
219
 
286
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
287
- // @ts-ignore
220
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
221
+ // @ts-ignore
288
222
  await executor({
289
223
  source,
290
224
  document: gql(source),
@@ -36,12 +36,16 @@ describe('opentelemetry', () => {
36
36
  describe('with local data', () =>
37
37
  {
38
38
  async function gateway() {
39
+ const localDataSources = Object.fromEntries(
40
+ fixtures.map((f) => [
41
+ f.name,
42
+ new LocalGraphQLDataSource(buildSubgraphSchema(f)),
43
+ ]),
44
+ );
39
45
  const gateway = new ApolloGateway({
40
46
  localServiceList: fixtures,
41
- buildService: service => {
42
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
43
- // @ts-ignore
44
- return new LocalGraphQLDataSource(buildSubgraphSchema([service]));
47
+ buildService(service) {
48
+ return localDataSources[service.name];
45
49
  },
46
50
  });
47
51
 
@@ -6,15 +6,20 @@ import { LocalGraphQLDataSource } from '../../datasources/LocalGraphQLDataSource
6
6
  import { ApolloGateway } from '../../';
7
7
  import { fixtures } from 'apollo-federation-integration-testsuite';
8
8
  import { QueryPlanner } from '@apollo/query-planner';
9
+
9
10
  it('caches the query plan for a request', async () => {
10
11
  const buildQueryPlanSpy = jest.spyOn(QueryPlanner.prototype, 'buildQueryPlan');
11
12
 
13
+ const localDataSources = Object.fromEntries(
14
+ fixtures.map((f) => [
15
+ f.name,
16
+ new LocalGraphQLDataSource(buildSubgraphSchema(f)),
17
+ ]),
18
+ );
12
19
  const gateway = new ApolloGateway({
13
20
  localServiceList: fixtures,
14
- buildService: service => {
15
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
16
- // @ts-ignore
17
- return new LocalGraphQLDataSource(buildSubgraphSchema([service]));
21
+ buildService(service) {
22
+ return localDataSources[service.name];
18
23
  },
19
24
  });
20
25
 
@@ -66,12 +71,17 @@ it('supports multiple operations and operationName', async () => {
66
71
  }
67
72
  `;
68
73
 
74
+ const localDataSources = Object.fromEntries(
75
+ fixtures.map((f) => [
76
+ f.name,
77
+ new LocalGraphQLDataSource(buildSubgraphSchema(f)),
78
+ ]),
79
+ );
80
+
69
81
  const gateway = new ApolloGateway({
70
82
  localServiceList: fixtures,
71
- buildService: service => {
72
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
73
- // @ts-ignore
74
- return new LocalGraphQLDataSource(buildSubgraphSchema([service]));
83
+ buildService(service) {
84
+ return localDataSources[service.name];
75
85
  },
76
86
  });
77
87
 
@@ -172,12 +182,15 @@ it('does not corrupt cached queryplan data across requests', async () => {
172
182
  },
173
183
  };
174
184
 
185
+ const dataSources: Record<string, LocalGraphQLDataSource> = {
186
+ a: new LocalGraphQLDataSource(buildSubgraphSchema(serviceA)),
187
+ b: new LocalGraphQLDataSource(buildSubgraphSchema(serviceB)),
188
+ };
189
+
175
190
  const gateway = new ApolloGateway({
176
191
  localServiceList: [serviceA, serviceB],
177
- buildService: service => {
178
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
179
- // @ts-ignore
180
- return new LocalGraphQLDataSource(buildSubgraphSchema([service]));
192
+ buildService(service) {
193
+ return dataSources[service.name];
181
194
  },
182
195
  });
183
196
 
@@ -1,17 +1,20 @@
1
1
  import { gunzipSync } from 'zlib';
2
2
  import nock from 'nock';
3
- import { GraphQLSchemaModule } from 'apollo-graphql';
4
3
  import gql from 'graphql-tag';
5
4
  import { buildSubgraphSchema } from '@apollo/subgraph';
6
5
  import { ApolloServer } from 'apollo-server';
7
6
  import { ApolloServerPluginUsageReporting } from 'apollo-server-core';
8
- import { execute, toPromise } from 'apollo-link';
9
- import { createHttpLink } from 'apollo-link-http';
7
+ import { execute } from '@apollo/client/link/core';
8
+ import { toPromise } from '@apollo/client/link/utils';
9
+ import { createHttpLink } from '@apollo/client/link/http';
10
10
  import fetch from 'node-fetch';
11
11
  import { ApolloGateway } from '../..';
12
12
  import { Plugin, Config, Refs } from 'pretty-format';
13
13
  import { Report, Trace } from 'apollo-reporting-protobuf';
14
14
  import { fixtures } from 'apollo-federation-integration-testsuite';
15
+ import { nockAfterEach, nockBeforeEach } from '../nockAssertions';
16
+ import { GraphQLSchemaModule } from '../../schema-helper';
17
+ import resolvable, { Resolvable } from '@josephg/resolvable';
15
18
 
16
19
  // Normalize specific fields that change often (eg timestamps) to static values,
17
20
  // to make snapshot testing viable. (If these helpers are more generally
@@ -88,19 +91,16 @@ describe('reporting', () => {
88
91
  let backendServers: ApolloServer[];
89
92
  let gatewayServer: ApolloServer;
90
93
  let gatewayUrl: string;
91
- let reportPromise: Promise<any>;
92
- let nockScope: nock.Scope;
94
+ let reportPromise: Resolvable<any>;
93
95
 
94
96
  beforeEach(async () => {
95
- let reportResolver: (report: any) => void;
96
- reportPromise = new Promise<any>((resolve) => {
97
- reportResolver = resolve;
98
- });
97
+ reportPromise = resolvable();
99
98
 
100
- nockScope = nock('https://usage-reporting.api.apollographql.com')
99
+ nockBeforeEach();
100
+ nock('https://usage-reporting.api.apollographql.com')
101
101
  .post('/api/ingress/traces')
102
102
  .reply(200, (_: any, requestBody: string) => {
103
- reportResolver(requestBody);
103
+ reportPromise.resolve(requestBody);
104
104
  return 'ok';
105
105
  });
106
106
 
@@ -137,7 +137,8 @@ describe('reporting', () => {
137
137
  if (gatewayServer) {
138
138
  await gatewayServer.stop();
139
139
  }
140
- nockScope.done();
140
+
141
+ nockAfterEach();
141
142
  });
142
143
 
143
144
  it(`queries three services`, async () => {
@@ -231,6 +232,34 @@ describe('reporting', () => {
231
232
  "tracesPerQuery": Object {
232
233
  "# -
233
234
  {me{name{first last}}topProducts{name}}": Object {
235
+ "referencedFieldsByType": Object {
236
+ "Name": Object {
237
+ "fieldNames": Array [
238
+ "first",
239
+ "last",
240
+ ],
241
+ "isInterface": false,
242
+ },
243
+ "Product": Object {
244
+ "fieldNames": Array [
245
+ "name",
246
+ ],
247
+ "isInterface": true,
248
+ },
249
+ "Query": Object {
250
+ "fieldNames": Array [
251
+ "me",
252
+ "topProducts",
253
+ ],
254
+ "isInterface": false,
255
+ },
256
+ "User": Object {
257
+ "fieldNames": Array [
258
+ "name",
259
+ ],
260
+ "isInterface": false,
261
+ },
262
+ },
234
263
  "trace": Array [
235
264
  Object {
236
265
  "cachePolicy": Object {
@@ -238,7 +267,6 @@ describe('reporting', () => {
238
267
  "scope": "PRIVATE",
239
268
  },
240
269
  "clientName": "",
241
- "clientReferenceId": "",
242
270
  "clientVersion": "",
243
271
  "details": Object {},
244
272
  "durationNs": 12345,
@@ -246,6 +274,7 @@ describe('reporting', () => {
246
274
  "nanos": 123000000,
247
275
  "seconds": "1562203363",
248
276
  },
277
+ "fieldExecutionWeight": 1,
249
278
  "forbiddenOperation": false,
250
279
  "fullQueryCacheHit": false,
251
280
  "http": Object {