@apollo/gateway 2.0.6-rc.0 → 2.1.0-alpha.1

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 (83) hide show
  1. package/dist/config.d.ts +1 -1
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js +2 -0
  4. package/dist/config.js.map +1 -1
  5. package/dist/datasources/RemoteGraphQLDataSource.d.ts.map +1 -1
  6. package/dist/datasources/RemoteGraphQLDataSource.js +2 -3
  7. package/dist/datasources/RemoteGraphQLDataSource.js.map +1 -1
  8. package/dist/datasources/types.d.ts +1 -0
  9. package/dist/datasources/types.d.ts.map +1 -1
  10. package/dist/executeQueryPlan.d.ts +2 -2
  11. package/dist/executeQueryPlan.d.ts.map +1 -1
  12. package/dist/executeQueryPlan.js +24 -16
  13. package/dist/executeQueryPlan.js.map +1 -1
  14. package/dist/index.d.ts +8 -8
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +27 -62
  17. package/dist/index.js.map +1 -1
  18. package/dist/logger.d.ts +3 -0
  19. package/dist/logger.d.ts.map +1 -0
  20. package/dist/logger.js +15 -0
  21. package/dist/logger.js.map +1 -0
  22. package/dist/operationContext.d.ts.map +1 -1
  23. package/dist/operationContext.js +3 -7
  24. package/dist/operationContext.js.map +1 -1
  25. package/dist/supergraphManagers/IntrospectAndCompose/index.d.ts +1 -1
  26. package/dist/supergraphManagers/IntrospectAndCompose/index.d.ts.map +1 -1
  27. package/dist/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.d.ts +1 -1
  28. package/dist/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.d.ts.map +1 -1
  29. package/dist/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.js.map +1 -1
  30. package/dist/supergraphManagers/UplinkSupergraphManager/index.d.ts +61 -0
  31. package/dist/supergraphManagers/UplinkSupergraphManager/index.d.ts.map +1 -0
  32. package/dist/supergraphManagers/UplinkSupergraphManager/index.js +209 -0
  33. package/dist/supergraphManagers/UplinkSupergraphManager/index.js.map +1 -0
  34. package/dist/supergraphManagers/{UplinkFetcher → UplinkSupergraphManager}/loadSupergraphSdlFromStorage.d.ts +8 -4
  35. package/dist/supergraphManagers/UplinkSupergraphManager/loadSupergraphSdlFromStorage.d.ts.map +1 -0
  36. package/dist/supergraphManagers/{UplinkFetcher → UplinkSupergraphManager}/loadSupergraphSdlFromStorage.js +20 -8
  37. package/dist/supergraphManagers/UplinkSupergraphManager/loadSupergraphSdlFromStorage.js.map +1 -0
  38. package/dist/supergraphManagers/{UplinkFetcher → UplinkSupergraphManager}/outOfBandReporter.d.ts +2 -1
  39. package/dist/supergraphManagers/UplinkSupergraphManager/outOfBandReporter.d.ts.map +1 -0
  40. package/dist/supergraphManagers/{UplinkFetcher → UplinkSupergraphManager}/outOfBandReporter.js +0 -0
  41. package/dist/supergraphManagers/UplinkSupergraphManager/outOfBandReporter.js.map +1 -0
  42. package/dist/supergraphManagers/UplinkSupergraphManager/types.d.ts +9 -0
  43. package/dist/supergraphManagers/UplinkSupergraphManager/types.d.ts.map +1 -0
  44. package/dist/supergraphManagers/UplinkSupergraphManager/types.js +5 -0
  45. package/dist/supergraphManagers/UplinkSupergraphManager/types.js.map +1 -0
  46. package/dist/supergraphManagers/index.d.ts +2 -2
  47. package/dist/supergraphManagers/index.d.ts.map +1 -1
  48. package/dist/supergraphManagers/index.js +17 -4
  49. package/dist/supergraphManagers/index.js.map +1 -1
  50. package/package.json +10 -10
  51. package/src/__tests__/executeQueryPlan.test.ts +199 -1
  52. package/src/__tests__/execution-utils.ts +5 -3
  53. package/src/__tests__/integration/abstract-types.test.ts +31 -65
  54. package/src/__tests__/integration/configuration.test.ts +2 -45
  55. package/src/__tests__/integration/managed.test.ts +292 -0
  56. package/src/__tests__/integration/networkRequests.test.ts +14 -54
  57. package/src/__tests__/integration/nockMocks.ts +7 -6
  58. package/src/config.ts +3 -1
  59. package/src/datasources/RemoteGraphQLDataSource.ts +1 -2
  60. package/src/datasources/types.ts +4 -0
  61. package/src/executeQueryPlan.ts +41 -30
  62. package/src/index.ts +33 -88
  63. package/src/logger.ts +11 -0
  64. package/src/operationContext.ts +5 -7
  65. package/src/supergraphManagers/IntrospectAndCompose/index.ts +1 -1
  66. package/src/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.ts +1 -1
  67. package/src/supergraphManagers/UplinkSupergraphManager/__tests__/UplinkSupergraphManager.test.ts +65 -0
  68. package/src/supergraphManagers/{UplinkFetcher → UplinkSupergraphManager}/__tests__/loadSupergraphSdlFromStorage.test.ts +51 -16
  69. package/src/supergraphManagers/{UplinkFetcher → UplinkSupergraphManager}/__tests__/tsconfig.json +0 -0
  70. package/src/supergraphManagers/UplinkSupergraphManager/index.ts +312 -0
  71. package/src/supergraphManagers/{UplinkFetcher → UplinkSupergraphManager}/loadSupergraphSdlFromStorage.ts +32 -12
  72. package/src/supergraphManagers/{UplinkFetcher → UplinkSupergraphManager}/outOfBandReporter.ts +2 -1
  73. package/src/supergraphManagers/UplinkSupergraphManager/types.ts +10 -0
  74. package/src/supergraphManagers/index.ts +2 -2
  75. package/dist/supergraphManagers/UplinkFetcher/index.d.ts +0 -35
  76. package/dist/supergraphManagers/UplinkFetcher/index.d.ts.map +0 -1
  77. package/dist/supergraphManagers/UplinkFetcher/index.js +0 -114
  78. package/dist/supergraphManagers/UplinkFetcher/index.js.map +0 -1
  79. package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.d.ts.map +0 -1
  80. package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.js.map +0 -1
  81. package/dist/supergraphManagers/UplinkFetcher/outOfBandReporter.d.ts.map +0 -1
  82. package/dist/supergraphManagers/UplinkFetcher/outOfBandReporter.js.map +0 -1
  83. package/src/supergraphManagers/UplinkFetcher/index.ts +0 -149
@@ -0,0 +1,292 @@
1
+ import mockedEnv from 'mocked-env';
2
+
3
+ import { ApolloGateway, UplinkSupergraphManager } from '@apollo/gateway';
4
+ import { ApolloServer } from 'apollo-server';
5
+ import { ApolloServerPluginUsageReportingDisabled } from 'apollo-server-core';
6
+
7
+ import { nockAfterEach, nockBeforeEach } from '../nockAssertions';
8
+ import {
9
+ mockSupergraphSdlRequestSuccess,
10
+ graphRef,
11
+ apiKey,
12
+ mockSupergraphSdlRequest,
13
+ } from '../integration/nockMocks';
14
+ import { getTestingSupergraphSdl } from '../execution-utils';
15
+
16
+ let gateway: ApolloGateway | undefined;
17
+ let server: ApolloServer | undefined;
18
+ let cleanUp: (() => void) | undefined;
19
+
20
+ beforeEach(() => {
21
+ nockBeforeEach();
22
+ });
23
+
24
+ afterEach(async () => {
25
+ if (server) {
26
+ await server.stop();
27
+ server = undefined;
28
+ }
29
+
30
+ if (gateway) {
31
+ await gateway.stop();
32
+ gateway = undefined;
33
+ }
34
+
35
+ nockAfterEach();
36
+
37
+ if (cleanUp) {
38
+ cleanUp();
39
+ cleanUp = undefined;
40
+ }
41
+ });
42
+
43
+ const logger = {
44
+ warn: jest.fn(),
45
+ debug: jest.fn(),
46
+ error: jest.fn(),
47
+ info: jest.fn(),
48
+ };
49
+
50
+ describe('minimal gateway', () => {
51
+ it('uses managed federation', async () => {
52
+ cleanUp = mockedEnv({
53
+ APOLLO_KEY: apiKey,
54
+ APOLLO_GRAPH_REF: graphRef,
55
+ });
56
+ mockSupergraphSdlRequestSuccess({ url: /.*?apollographql.com/ });
57
+
58
+ gateway = new ApolloGateway({ logger });
59
+ server = new ApolloServer({
60
+ gateway,
61
+ plugins: [ApolloServerPluginUsageReportingDisabled()],
62
+ });
63
+ await server.listen({ port: 0 });
64
+ expect(gateway.supergraphManager).toBeInstanceOf(UplinkSupergraphManager);
65
+ });
66
+
67
+ it('fetches from provided `uplinkEndpoints`', async () => {
68
+ cleanUp = mockedEnv({
69
+ APOLLO_KEY: apiKey,
70
+ APOLLO_GRAPH_REF: graphRef,
71
+ });
72
+
73
+ const uplinkEndpoint = 'https://example.com';
74
+ mockSupergraphSdlRequestSuccess({ url: uplinkEndpoint });
75
+
76
+ gateway = new ApolloGateway({ logger, uplinkEndpoints: [uplinkEndpoint] });
77
+ server = new ApolloServer({
78
+ gateway,
79
+ plugins: [ApolloServerPluginUsageReportingDisabled()],
80
+ });
81
+ await server.listen({ port: 0 });
82
+ expect(gateway.supergraphManager).toBeInstanceOf(UplinkSupergraphManager);
83
+ const uplinkManager = gateway.supergraphManager as UplinkSupergraphManager;
84
+ expect(uplinkManager.uplinkEndpoints).toEqual([uplinkEndpoint]);
85
+ });
86
+
87
+ it('fetches from (deprecated) provided `schemaConfigDeliveryEndpoint`', async () => {
88
+ cleanUp = mockedEnv({
89
+ APOLLO_KEY: apiKey,
90
+ APOLLO_GRAPH_REF: graphRef,
91
+ });
92
+
93
+ const schemaConfigDeliveryEndpoint = 'https://example.com';
94
+ mockSupergraphSdlRequestSuccess({ url: schemaConfigDeliveryEndpoint });
95
+
96
+ gateway = new ApolloGateway({ logger, schemaConfigDeliveryEndpoint });
97
+ server = new ApolloServer({
98
+ gateway,
99
+ plugins: [ApolloServerPluginUsageReportingDisabled()],
100
+ });
101
+ await server.listen({ port: 0 });
102
+ expect(gateway.supergraphManager).toBeInstanceOf(UplinkSupergraphManager);
103
+ const uplinkManager = gateway.supergraphManager as UplinkSupergraphManager;
104
+ expect(uplinkManager.uplinkEndpoints).toEqual([
105
+ schemaConfigDeliveryEndpoint,
106
+ ]);
107
+ });
108
+ });
109
+
110
+ describe('Managed gateway with explicit UplinkSupergraphManager', () => {
111
+ it('waits for supergraph schema to load', async () => {
112
+ mockSupergraphSdlRequestSuccess({ url: /.*?apollographql.com/ });
113
+
114
+ gateway = new ApolloGateway({
115
+ logger,
116
+ supergraphSdl: new UplinkSupergraphManager({
117
+ apiKey,
118
+ graphRef,
119
+ logger,
120
+ }),
121
+ });
122
+ await expect(gateway.load()).resolves.not.toThrow();
123
+ });
124
+
125
+ it('invokes callback if uplink throws an error during init', async () => {
126
+ mockSupergraphSdlRequest(null, /.*?apollographql.com/).reply(500);
127
+
128
+ const supergraphSchema = getTestingSupergraphSdl();
129
+ let hasFired;
130
+ gateway = new ApolloGateway({
131
+ logger,
132
+ supergraphSdl: new UplinkSupergraphManager({
133
+ apiKey,
134
+ graphRef,
135
+ logger,
136
+ maxRetries: 0,
137
+ async onFailureToFetchSupergraphSdlDuringInit() {
138
+ hasFired = true;
139
+ return supergraphSchema;
140
+ },
141
+ }),
142
+ });
143
+
144
+ await expect(gateway.load()).resolves.not.toThrow();
145
+ expect(gateway.__testing().supergraphSdl).toBe(supergraphSchema);
146
+ expect(hasFired).toBeTruthy();
147
+ });
148
+
149
+ it('invokes callback if uplink throws an error after init', async () => {
150
+ // This is kinda wonky to read: we're responding the first time with success, then the next fetch should fail
151
+ mockSupergraphSdlRequestSuccess({ url: /.*?apollographql.com/ })
152
+ .post('/')
153
+ .reply(500);
154
+
155
+ const supergraphSchema = getTestingSupergraphSdl();
156
+ let hasFired;
157
+ let uplinkManager = new UplinkSupergraphManager({
158
+ apiKey,
159
+ graphRef,
160
+ logger,
161
+ maxRetries: 0,
162
+ async onFailureToFetchSupergraphSdlAfterInit() {
163
+ hasFired = true;
164
+ return supergraphSchema;
165
+ },
166
+ });
167
+ // Set pollIntervalMs lower than the typically allowed value so we don't wait 10s between polling
168
+ uplinkManager['pollIntervalMs'] = 0;
169
+
170
+ gateway = new ApolloGateway({
171
+ logger,
172
+ supergraphSdl: uplinkManager,
173
+ });
174
+
175
+ await expect(gateway.load()).resolves.not.toThrow();
176
+ expect(hasFired).toBeFalsy();
177
+
178
+ await uplinkManager.nextFetch();
179
+
180
+ expect(hasFired).toBeTruthy();
181
+ });
182
+
183
+ it.each([
184
+ ['x', 'Syntax Error: Unexpected Name "x".'],
185
+ ['', 'Invalid supergraph schema supplied during initialization.'],
186
+ [' ', 'Syntax Error: Unexpected <EOF>.'],
187
+ ['type Query {hi: String}', 'Invalid supergraph: must be a core schema'],
188
+ ])(
189
+ 'throws if invalid supergraph schema returned from callback during init: %p',
190
+ async (schemaText, expectedMessage) => {
191
+ mockSupergraphSdlRequest(null, /.*?apollographql.com/).reply(500);
192
+
193
+ gateway = new ApolloGateway({
194
+ logger,
195
+ supergraphSdl: new UplinkSupergraphManager({
196
+ apiKey,
197
+ graphRef,
198
+ logger,
199
+ maxRetries: 0,
200
+ async onFailureToFetchSupergraphSdlDuringInit() {
201
+ return schemaText;
202
+ },
203
+ }),
204
+ });
205
+
206
+ await expect(gateway.load()).rejects.toThrowError(expectedMessage);
207
+ },
208
+ );
209
+
210
+ it.each([
211
+ ['x', 'Syntax Error: Unexpected Name "x".'],
212
+ [' ', 'Syntax Error: Unexpected <EOF>.'],
213
+ ['type Query {hi: String}', 'Invalid supergraph: must be a core schema'],
214
+ ])(
215
+ 'throws if invalid supergraph schema returned from callback after init: %p',
216
+ async (schemaText, expectedMessage) => {
217
+ // This is kinda wonky to read: we're responding the first time with success, then the next fetch should fail
218
+ mockSupergraphSdlRequestSuccess({ url: /.*?apollographql.com/ })
219
+ .post('/')
220
+ .reply(500);
221
+
222
+ let hasFired;
223
+ let uplinkManager = new UplinkSupergraphManager({
224
+ apiKey,
225
+ graphRef,
226
+ logger,
227
+ maxRetries: 0,
228
+ async onFailureToFetchSupergraphSdlAfterInit() {
229
+ hasFired = true;
230
+ return schemaText;
231
+ },
232
+ });
233
+ // Set pollIntervalMs lower than the typically allowed value so we don't wait 10s between polling
234
+ uplinkManager['pollIntervalMs'] = 0;
235
+
236
+ gateway = new ApolloGateway({
237
+ logger,
238
+ supergraphSdl: uplinkManager
239
+ });
240
+
241
+ await expect(gateway.load()).resolves.not.toThrow();
242
+ expect(hasFired).toBeFalsy();
243
+
244
+ await uplinkManager.nextFetch();
245
+
246
+ expect(hasFired).toBeTruthy();
247
+ expect(logger.error).toBeCalledWith(
248
+ `UplinkSupergraphManager failed to update supergraph with the following error: ${expectedMessage}`,
249
+ );
250
+ },
251
+ );
252
+
253
+ it.each([null, ''])(
254
+ 'uses existing supergraph schema if false-y value returned from callback after init: %p',
255
+ async (schemaText) => {
256
+ // This is kinda wonky to read: we're responding the first time with success, then the next fetch should fail
257
+ mockSupergraphSdlRequestSuccess({ url: /.*?apollographql.com/ })
258
+ .post('/')
259
+ .reply(500);
260
+
261
+ let hasFired;
262
+ let uplinkManager = new UplinkSupergraphManager({
263
+ apiKey,
264
+ graphRef,
265
+ logger,
266
+ maxRetries: 0,
267
+
268
+ async onFailureToFetchSupergraphSdlAfterInit() {
269
+ hasFired = true;
270
+ return schemaText;
271
+ },
272
+ });
273
+ // Set pollIntervalMs lower than the typically allowed value so we don't wait 10s between polling
274
+ uplinkManager['pollIntervalMs'] = 0;
275
+
276
+ gateway = new ApolloGateway({
277
+ logger,
278
+ supergraphSdl: uplinkManager,
279
+ });
280
+
281
+ await expect(gateway.load()).resolves.not.toThrow();
282
+ expect(hasFired).toBeFalsy();
283
+
284
+ await uplinkManager.nextFetch();
285
+
286
+ expect(hasFired).toBeTruthy();
287
+
288
+ const supergraphSchema = getTestingSupergraphSdl();
289
+ expect(gateway.__testing().supergraphSdl).toBe(supergraphSchema);
290
+ },
291
+ );
292
+ });
@@ -2,7 +2,7 @@ import gql from 'graphql-tag';
2
2
  import { GraphQLObjectType, GraphQLSchema } from 'graphql';
3
3
  import mockedEnv from 'mocked-env';
4
4
  import type { Logger } from '@apollo/utils.logger';
5
- import { ApolloGateway } from '../..';
5
+ import { ApolloGateway, UplinkSupergraphManager } from '../..';
6
6
  import {
7
7
  mockSdlQuerySuccess,
8
8
  mockServiceHealthCheckSuccess,
@@ -56,8 +56,12 @@ function getRootQueryFields(schema?: GraphQLSchema): string[] {
56
56
  let logger: Logger;
57
57
  let gateway: ApolloGateway | null = null;
58
58
  let cleanUp: (() => void) | null = null;
59
+ let originalMinPollInterval = UplinkSupergraphManager.MIN_POLL_INTERVAL_MS;
59
60
 
60
61
  beforeEach(() => {
62
+ // Set the min poll interval artificially low so we're not waiting during tests
63
+ // @ts-ignore
64
+ UplinkSupergraphManager['MIN_POLL_INTERVAL_MS'] = 100;
61
65
  nockBeforeEach();
62
66
 
63
67
  const warn = jest.fn();
@@ -74,13 +78,15 @@ beforeEach(() => {
74
78
  });
75
79
 
76
80
  afterEach(async () => {
77
- nockAfterEach();
78
-
81
+ // @ts-ignore
82
+ UplinkSupergraphManager['MIN_POLL_INTERVAL_MS'] = originalMinPollInterval;
79
83
  if (gateway) {
80
84
  await gateway.stop();
81
85
  gateway = null;
82
86
  }
83
87
 
88
+ nockAfterEach();
89
+
84
90
  if (cleanUp) {
85
91
  cleanUp();
86
92
  cleanUp = null;
@@ -90,7 +96,7 @@ afterEach(async () => {
90
96
  it('Queries remote endpoints for their SDLs', async () => {
91
97
  mockSdlQuerySuccess(simpleService);
92
98
 
93
- gateway = new ApolloGateway({ serviceList: [simpleService] });
99
+ gateway = new ApolloGateway({ serviceList: [simpleService], logger });
94
100
  await gateway.load();
95
101
  expect(gateway.schema!.getType('User')!.description).toBe('This is my User');
96
102
  });
@@ -139,8 +145,6 @@ it('Updates Supergraph SDL from remote storage', async () => {
139
145
  logger,
140
146
  uplinkEndpoints: [mockCloudConfigUrl1],
141
147
  });
142
- // for testing purposes, a short pollInterval is ideal so we'll override here
143
- gateway['pollIntervalInMs'] = 100;
144
148
 
145
149
  const schemas: GraphQLSchema[] = [];
146
150
  gateway.onSchemaLoadOrUpdate(({ apiSchema }) => {
@@ -183,13 +187,6 @@ describe('Supergraph SDL update failures', () => {
183
187
  ).rejects.toThrowErrorMatchingInlineSnapshot(
184
188
  `"An error occurred while fetching your schema from Apollo: 401 Unauthorized"`,
185
189
  );
186
-
187
- await expect(gateway.stop()).rejects.toThrowErrorMatchingInlineSnapshot(
188
- `"ApolloGateway.stop does not need to be called before ApolloGateway.load is called successfully"`,
189
- );
190
- // Set to `null` so we don't try to call `stop` on it in the `afterEach`,
191
- // which triggers a different error that we're not testing for here.
192
- gateway = null;
193
190
  });
194
191
 
195
192
  it('Handles arbitrary fetch failures (non 200 response)', async () => {
@@ -206,14 +203,11 @@ describe('Supergraph SDL update failures', () => {
206
203
  uplinkMaxRetries: 0,
207
204
  });
208
205
 
209
- // for testing purposes, a short pollInterval is ideal so we'll override here
210
- gateway['pollIntervalInMs'] = 100;
211
-
212
206
  await gateway.load(mockApolloConfig);
213
207
  await errorLoggedPromise;
214
208
 
215
209
  expect(logger.error).toHaveBeenCalledWith(
216
- 'UplinkFetcher failed to update supergraph with the following error: An error occurred while fetching your schema from Apollo: 500 Internal Server Error',
210
+ 'UplinkSupergraphManager failed to update supergraph with the following error: An error occurred while fetching your schema from Apollo: 500 Internal Server Error',
217
211
  );
218
212
  });
219
213
 
@@ -238,14 +232,12 @@ describe('Supergraph SDL update failures', () => {
238
232
  uplinkEndpoints: [mockCloudConfigUrl1],
239
233
  uplinkMaxRetries: 0,
240
234
  });
241
- // for testing purposes, a short pollInterval is ideal so we'll override here
242
- gateway['pollIntervalInMs'] = 100;
243
235
 
244
236
  await gateway.load(mockApolloConfig);
245
237
  await errorLoggedPromise;
246
238
 
247
239
  expect(logger.error).toHaveBeenCalledWith(
248
- `UplinkFetcher failed to update supergraph with the following error: An error occurred while fetching your schema from Apollo: \nCannot query field "fail" on type "Query".`,
240
+ `UplinkSupergraphManager failed to update supergraph with the following error: An error occurred while fetching your schema from Apollo: \nCannot query field "fail" on type "Query".`,
249
241
  );
250
242
  });
251
243
 
@@ -272,14 +264,12 @@ describe('Supergraph SDL update failures', () => {
272
264
  logger,
273
265
  uplinkEndpoints: [mockCloudConfigUrl1],
274
266
  });
275
- // for testing purposes, a short pollInterval is ideal so we'll override here
276
- gateway['pollIntervalInMs'] = 100;
277
267
 
278
268
  await gateway.load(mockApolloConfig);
279
269
  await errorLoggedPromise;
280
270
 
281
271
  expect(logger.error).toHaveBeenCalledWith(
282
- 'UplinkFetcher failed to update supergraph with the following error: Syntax Error: Unexpected Name "Syntax".',
272
+ 'UplinkSupergraphManager failed to update supergraph with the following error: Syntax Error: Unexpected Name "Syntax".',
283
273
  );
284
274
  expect(gateway.schema).toBeTruthy();
285
275
  });
@@ -302,8 +292,6 @@ describe('Supergraph SDL update failures', () => {
302
292
  logger,
303
293
  uplinkEndpoints: [mockCloudConfigUrl1],
304
294
  });
305
- // for testing purposes, a short pollInterval is ideal so we'll override here
306
- gateway['pollIntervalInMs'] = 100;
307
295
 
308
296
  await expect(
309
297
  gateway.load(mockApolloConfig),
@@ -312,10 +300,6 @@ describe('Supergraph SDL update failures', () => {
312
300
  );
313
301
 
314
302
  expect(gateway['state'].phase).toEqual('failed to load');
315
-
316
- // Set to `null` so we don't try to call `stop` on it in the `afterEach`,
317
- // which triggers a different error that we're not testing for here.
318
- gateway = null;
319
303
  });
320
304
  });
321
305
 
@@ -343,8 +327,6 @@ it('Rollsback to a previous schema when triggered', async () => {
343
327
  logger,
344
328
  uplinkEndpoints: [mockCloudConfigUrl1],
345
329
  });
346
- // for testing purposes, a short pollInterval is ideal so we'll override here
347
- gateway['pollIntervalInMs'] = 100;
348
330
 
349
331
  gateway.onSchemaChange(onChange);
350
332
  await gateway.load(mockApolloConfig);
@@ -406,14 +388,6 @@ describe('Downstream service health checks', () => {
406
388
  "The gateway subgraphs health check failed. Updating to the provided \`supergraphSdl\` will likely result in future request failures to subgraphs. The following error occurred during the health check:
407
389
  [accounts]: 500: Internal Server Error"
408
390
  `);
409
-
410
- await expect(gateway.stop()).rejects.toThrowErrorMatchingInlineSnapshot(
411
- `"ApolloGateway.stop does not need to be called before ApolloGateway.load is called successfully"`,
412
- );
413
-
414
- // Set to `null` so we don't try to call `stop` on it in the `afterEach`,
415
- // which triggers a different error that we're not testing for here.
416
- gateway = null;
417
391
  });
418
392
  });
419
393
 
@@ -427,8 +401,6 @@ describe('Downstream service health checks', () => {
427
401
  logger,
428
402
  uplinkEndpoints: [mockCloudConfigUrl1],
429
403
  });
430
- // for testing purposes, a short pollInterval is ideal so we'll override here
431
- gateway['pollIntervalInMs'] = 100;
432
404
 
433
405
  await gateway.load(mockApolloConfig);
434
406
  await gateway.stop();
@@ -471,14 +443,6 @@ describe('Downstream service health checks', () => {
471
443
  "The gateway subgraphs health check failed. Updating to the provided \`supergraphSdl\` will likely result in future request failures to subgraphs. The following error occurred during the health check:
472
444
  [accounts]: 500: Internal Server Error"
473
445
  `);
474
-
475
- await expect(gateway.stop()).rejects.toThrowErrorMatchingInlineSnapshot(
476
- `"ApolloGateway.stop does not need to be called before ApolloGateway.load is called successfully"`,
477
- );
478
-
479
- // Set to `null` so we don't try to call `stop` on it in the `afterEach`,
480
- // which triggers a different error that we're not testing for here.
481
- gateway = null;
482
446
  });
483
447
 
484
448
  // This test has been flaky for a long time, and fails consistently after changes
@@ -509,8 +473,6 @@ describe('Downstream service health checks', () => {
509
473
  logger,
510
474
  uplinkEndpoints: [mockCloudConfigUrl1],
511
475
  });
512
- // for testing purposes, a short pollInterval is ideal so we'll override here
513
- gateway['pollIntervalInMs'] = 100;
514
476
 
515
477
  gateway.onSchemaChange(onChange);
516
478
  await gateway.load(mockApolloConfig);
@@ -553,8 +515,6 @@ describe('Downstream service health checks', () => {
553
515
  logger,
554
516
  uplinkEndpoints: [mockCloudConfigUrl1],
555
517
  });
556
- // for testing purposes, a short pollInterval is ideal so we'll override here
557
- gateway['pollIntervalInMs'] = 100;
558
518
 
559
519
  const updateSpy = jest.fn();
560
520
  gateway.onSchemaLoadOrUpdate(() => updateSpy());
@@ -568,7 +528,7 @@ describe('Downstream service health checks', () => {
568
528
 
569
529
  await errorLoggedPromise;
570
530
  expect(logger.error).toHaveBeenCalledWith(
571
- `UplinkFetcher failed to update supergraph with the following error: The gateway subgraphs health check failed. Updating to the provided \`supergraphSdl\` will likely result in future request failures to subgraphs. The following error occurred during the health check:\n[accounts]: 500: Internal Server Error`,
531
+ `UplinkSupergraphManager failed to update supergraph with the following error: The gateway subgraphs health check failed. Updating to the provided \`supergraphSdl\` will likely result in future request failures to subgraphs. The following error occurred during the health check:\n[accounts]: 500: Internal Server Error`,
572
532
  );
573
533
 
574
534
  // At this point, the mock update should have been called but the schema
@@ -1,6 +1,6 @@
1
1
  import nock from 'nock';
2
2
  import { HEALTH_CHECK_QUERY, SERVICE_DEFINITION_QUERY } from '../..';
3
- import { SUPERGRAPH_SDL_QUERY } from '../../supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage';
3
+ import { SUPERGRAPH_SDL_QUERY } from '../../supergraphManagers/UplinkSupergraphManager/loadSupergraphSdlFromStorage';
4
4
  import { getTestingSupergraphSdl } from '../../__tests__/execution-utils';
5
5
  import { print } from 'graphql';
6
6
  import { Fixture, fixtures as testingFixtures } from 'apollo-federation-integration-testsuite';
@@ -83,7 +83,7 @@ export const mockCloudConfigUrl3 =
83
83
  export const mockOutOfBandReporterUrl =
84
84
  'https://example.outofbandreporter.com/monitoring/';
85
85
 
86
- export function mockSupergraphSdlRequestIfAfter(ifAfter: string | null, url: string = mockCloudConfigUrl1) {
86
+ export function mockSupergraphSdlRequestIfAfter(ifAfter: string | null, url: string | RegExp = mockCloudConfigUrl1) {
87
87
  return gatewayNock(url).post('/', {
88
88
  query: SUPERGRAPH_SDL_QUERY,
89
89
  variables: {
@@ -94,7 +94,7 @@ export function mockSupergraphSdlRequestIfAfter(ifAfter: string | null, url: str
94
94
  });
95
95
  }
96
96
 
97
- export function mockSupergraphSdlRequest(ifAfter: string | null = null, url: string = mockCloudConfigUrl1) {
97
+ export function mockSupergraphSdlRequest(ifAfter: string | null = null, url: string | RegExp = mockCloudConfigUrl1) {
98
98
  return mockSupergraphSdlRequestIfAfter(ifAfter, url);
99
99
  }
100
100
 
@@ -102,11 +102,12 @@ export function mockSupergraphSdlRequestSuccessIfAfter(
102
102
  ifAfter: string | null = null,
103
103
  id: string = 'originalId-1234',
104
104
  supergraphSdl: string = getTestingSupergraphSdl(),
105
+ url: string | RegExp = mockCloudConfigUrl1,
105
106
  ) {
106
107
  if (supergraphSdl == null) {
107
108
  supergraphSdl = getTestingSupergraphSdl();
108
109
  }
109
- return mockSupergraphSdlRequestIfAfter(ifAfter).reply(
110
+ return mockSupergraphSdlRequestIfAfter(ifAfter, url).reply(
110
111
  200,
111
112
  JSON.stringify({
112
113
  data: {
@@ -136,8 +137,8 @@ export function mockSupergraphSdlRequestIfAfterUnchanged(
136
137
  );
137
138
  }
138
139
 
139
- export function mockSupergraphSdlRequestSuccess() {
140
- return mockSupergraphSdlRequestSuccessIfAfter(null);
140
+ export function mockSupergraphSdlRequestSuccess({supergraphSdl = getTestingSupergraphSdl(), url = mockCloudConfigUrl1}: {supergraphSdl?: string, url?: string | RegExp} = {}) {
141
+ return mockSupergraphSdlRequestSuccessIfAfter(null, undefined, supergraphSdl, url);
141
142
  }
142
143
 
143
144
  export function mockOutOfBandReportRequest() {
package/src/config.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { GraphQLError, GraphQLSchema } from 'graphql';
2
- import { HeadersInit } from 'node-fetch';
2
+ import type { HeadersInit } from 'node-fetch';
3
3
  import { GraphQLRequestContextExecutionDidStart } from 'apollo-server-types';
4
4
  import type { Logger } from '@apollo/utils.logger';
5
5
  import { GraphQLDataSource } from './datasources/types';
@@ -8,6 +8,7 @@ import { OperationContext } from './operationContext';
8
8
  import { ServiceMap } from './executeQueryPlan';
9
9
  import { ServiceDefinition } from "@apollo/federation-internals";
10
10
  import { Fetcher } from '@apollo/utils.fetcher';
11
+ import { UplinkSupergraphManager } from './supergraphManagers';
11
12
 
12
13
  export type ServiceEndpointDefinition = Pick<ServiceDefinition, 'name' | 'url'>;
13
14
 
@@ -325,6 +326,7 @@ export function isManagedConfig(
325
326
  'schemaConfigDeliveryEndpoint' in config ||
326
327
  'uplinkEndpoints' in config ||
327
328
  'fallbackPollIntervalInMs' in config ||
329
+ (isSupergraphManagerConfig(config) && config.supergraphSdl instanceof UplinkSupergraphManager) ||
328
330
  (!isLocalConfig(config) &&
329
331
  !isStaticSupergraphSdlConfig(config) &&
330
332
  !isManuallyManagedConfig(config))
@@ -118,8 +118,7 @@ export class RemoteGraphQLDataSource<
118
118
  // there.
119
119
  const overallCachePolicy =
120
120
  this.honorSubgraphCacheControlHeader &&
121
- options.kind === GraphQLDataSourceRequestKind.INCOMING_OPERATION &&
122
- options.incomingRequestContext.overallCachePolicy?.restrict
121
+ options.kind === GraphQLDataSourceRequestKind.INCOMING_OPERATION
123
122
  ? options.incomingRequestContext.overallCachePolicy
124
123
  : null;
125
124
 
@@ -39,6 +39,10 @@ export type GraphQLDataSourceProcessOptions<
39
39
  * checking `kind`).
40
40
  */
41
41
  context: GraphQLRequestContext<TContext>['context'];
42
+ /**
43
+ * The document representation of the request's query being sent to the subgraph, if available.
44
+ */
45
+ document?: GraphQLRequestContext<TContext>['document'];
42
46
  }
43
47
  | {
44
48
  kind: