@apollo/gateway 0.43.0 → 0.45.0-alpha.0

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 (39) hide show
  1. package/CHANGELOG.md +14 -2
  2. package/dist/__generated__/graphqlTypes.d.ts +13 -11
  3. package/dist/__generated__/graphqlTypes.d.ts.map +1 -1
  4. package/dist/__generated__/graphqlTypes.js.map +1 -1
  5. package/dist/config.d.ts +3 -8
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +6 -17
  8. package/dist/config.js.map +1 -1
  9. package/dist/index.d.ts +4 -3
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +33 -33
  12. package/dist/index.js.map +1 -1
  13. package/dist/loadSupergraphSdlFromStorage.d.ts +15 -6
  14. package/dist/loadSupergraphSdlFromStorage.d.ts.map +1 -1
  15. package/dist/loadSupergraphSdlFromStorage.js +40 -9
  16. package/dist/loadSupergraphSdlFromStorage.js.map +1 -1
  17. package/dist/outOfBandReporter.d.ts +10 -12
  18. package/dist/outOfBandReporter.d.ts.map +1 -1
  19. package/dist/outOfBandReporter.js +70 -73
  20. package/dist/outOfBandReporter.js.map +1 -1
  21. package/package.json +8 -8
  22. package/src/__generated__/graphqlTypes.ts +13 -11
  23. package/src/__tests__/gateway/reporting.test.ts +5 -3
  24. package/src/__tests__/integration/configuration.test.ts +32 -11
  25. package/src/__tests__/integration/networkRequests.test.ts +44 -32
  26. package/src/__tests__/integration/nockMocks.ts +42 -8
  27. package/src/__tests__/loadSupergraphSdlFromStorage.test.ts +129 -375
  28. package/src/__tests__/nockAssertions.ts +20 -0
  29. package/src/config.ts +10 -43
  30. package/src/index.ts +43 -54
  31. package/src/loadSupergraphSdlFromStorage.ts +61 -12
  32. package/src/outOfBandReporter.ts +87 -89
  33. package/dist/legacyLoadServicesFromStorage.d.ts +0 -20
  34. package/dist/legacyLoadServicesFromStorage.d.ts.map +0 -1
  35. package/dist/legacyLoadServicesFromStorage.js +0 -62
  36. package/dist/legacyLoadServicesFromStorage.js.map +0 -1
  37. package/src/__tests__/integration/legacyNetworkRequests.test.ts +0 -279
  38. package/src/__tests__/integration/legacyNockMocks.ts +0 -113
  39. package/src/legacyLoadServicesFromStorage.ts +0 -170
@@ -1,4 +1,3 @@
1
- import nock from 'nock';
2
1
  import gql from 'graphql-tag';
3
2
  import { DocumentNode, GraphQLObjectType, GraphQLSchema } from 'graphql';
4
3
  import mockedEnv from 'mocked-env';
@@ -12,7 +11,9 @@ import {
12
11
  mockSupergraphSdlRequestSuccess,
13
12
  mockSupergraphSdlRequest,
14
13
  mockApolloConfig,
15
- mockCloudConfigUrl,
14
+ mockCloudConfigUrl1,
15
+ mockSupergraphSdlRequestIfAfter,
16
+ mockSupergraphSdlRequestSuccessIfAfter,
16
17
  } from './nockMocks';
17
18
  import {
18
19
  accounts,
@@ -24,6 +25,7 @@ import {
24
25
  reviews,
25
26
  } from 'apollo-federation-integration-testsuite';
26
27
  import { getTestingSupergraphSdl } from '../execution-utils';
28
+ import { nockAfterEach, nockBeforeEach } from '../nockAssertions';
27
29
 
28
30
  export interface MockService {
29
31
  name: string;
@@ -60,7 +62,7 @@ let gateway: ApolloGateway | null = null;
60
62
  let cleanUp: (() => void) | null = null;
61
63
 
62
64
  beforeEach(() => {
63
- if (!nock.isActive()) nock.activate();
65
+ nockBeforeEach();
64
66
 
65
67
  const warn = jest.fn();
66
68
  const debug = jest.fn();
@@ -76,9 +78,8 @@ beforeEach(() => {
76
78
  });
77
79
 
78
80
  afterEach(async () => {
79
- expect(nock.isDone()).toBeTruthy();
80
- nock.cleanAll();
81
- nock.restore();
81
+ nockAfterEach();
82
+
82
83
  if (gateway) {
83
84
  await gateway.stop();
84
85
  gateway = null;
@@ -98,13 +99,12 @@ it('Queries remote endpoints for their SDLs', async () => {
98
99
  expect(gateway.schema!.getType('User')!.description).toBe('This is my User');
99
100
  });
100
101
 
101
- // TODO(trevor:cloudconfig): Remove all usages of the experimental config option
102
102
  it('Fetches Supergraph SDL from remote storage', async () => {
103
103
  mockSupergraphSdlRequestSuccess();
104
104
 
105
105
  gateway = new ApolloGateway({
106
106
  logger,
107
- schemaConfigDeliveryEndpoint: mockCloudConfigUrl,
107
+ uplinkEndpoints: [mockCloudConfigUrl1],
108
108
  });
109
109
 
110
110
  await gateway.load(mockApolloConfig);
@@ -112,10 +112,9 @@ it('Fetches Supergraph SDL from remote storage', async () => {
112
112
  expect(gateway.schema?.getType('User')).toBeTruthy();
113
113
  });
114
114
 
115
- // TODO(trevor:cloudconfig): This test should evolve to demonstrate overriding the default in the future
116
115
  it('Fetches Supergraph SDL from remote storage using a configured env variable', async () => {
117
116
  cleanUp = mockedEnv({
118
- APOLLO_SCHEMA_CONFIG_DELIVERY_ENDPOINT: mockCloudConfigUrl,
117
+ APOLLO_SCHEMA_CONFIG_DELIVERY_ENDPOINT: mockCloudConfigUrl1,
119
118
  });
120
119
  mockSupergraphSdlRequestSuccess();
121
120
 
@@ -130,7 +129,11 @@ it('Fetches Supergraph SDL from remote storage using a configured env variable',
130
129
 
131
130
  it('Updates Supergraph SDL from remote storage', async () => {
132
131
  mockSupergraphSdlRequestSuccess();
133
- mockSupergraphSdlRequestSuccess(getTestingSupergraphSdl(fixturesWithUpdate), 'updatedId-5678');
132
+ mockSupergraphSdlRequestSuccessIfAfter(
133
+ 'originalId-1234',
134
+ 'updatedId-5678',
135
+ getTestingSupergraphSdl(fixturesWithUpdate),
136
+ );
134
137
 
135
138
  // This test is only interested in the second time the gateway notifies of an
136
139
  // update, since the first happens on load.
@@ -145,11 +148,11 @@ it('Updates Supergraph SDL from remote storage', async () => {
145
148
 
146
149
  gateway = new ApolloGateway({
147
150
  logger,
148
- schemaConfigDeliveryEndpoint: mockCloudConfigUrl,
151
+ uplinkEndpoints: [mockCloudConfigUrl1],
149
152
  });
150
153
  // @ts-ignore for testing purposes, a short pollInterval is ideal so we'll override here
151
154
  gateway.experimental_pollInterval = 100;
152
- gateway.onSchemaChange(schemaChangeCallback);
155
+ gateway.onSchemaLoadOrUpdate(schemaChangeCallback);
153
156
 
154
157
  await gateway.load(mockApolloConfig);
155
158
  expect(gateway['compositionId']).toMatchInlineSnapshot(`"originalId-1234"`);
@@ -164,7 +167,8 @@ describe('Supergraph SDL update failures', () => {
164
167
 
165
168
  gateway = new ApolloGateway({
166
169
  logger,
167
- schemaConfigDeliveryEndpoint: mockCloudConfigUrl,
170
+ uplinkEndpoints: [mockCloudConfigUrl1],
171
+ uplinkMaxRetries: 0
168
172
  });
169
173
 
170
174
  await expect(
@@ -183,7 +187,7 @@ describe('Supergraph SDL update failures', () => {
183
187
 
184
188
  it('Handles arbitrary fetch failures (non 200 response)', async () => {
185
189
  mockSupergraphSdlRequestSuccess();
186
- mockSupergraphSdlRequest().reply(500);
190
+ mockSupergraphSdlRequestIfAfter('originalId-1234').reply(500);
187
191
 
188
192
  // Spy on logger.error so we can just await once it's been called
189
193
  let errorLogged: Function;
@@ -192,7 +196,8 @@ describe('Supergraph SDL update failures', () => {
192
196
 
193
197
  gateway = new ApolloGateway({
194
198
  logger,
195
- schemaConfigDeliveryEndpoint: mockCloudConfigUrl,
199
+ uplinkEndpoints: [mockCloudConfigUrl1],
200
+ uplinkMaxRetries: 0
196
201
  });
197
202
 
198
203
  // @ts-ignore for testing purposes, a short pollInterval is ideal so we'll override here
@@ -208,7 +213,7 @@ describe('Supergraph SDL update failures', () => {
208
213
 
209
214
  it('Handles GraphQL errors', async () => {
210
215
  mockSupergraphSdlRequestSuccess();
211
- mockSupergraphSdlRequest().reply(200, {
216
+ mockSupergraphSdlRequest('originalId-1234').reply(200, {
212
217
  errors: [
213
218
  {
214
219
  message: 'Cannot query field "fail" on type "Query".',
@@ -225,7 +230,8 @@ describe('Supergraph SDL update failures', () => {
225
230
 
226
231
  gateway = new ApolloGateway({
227
232
  logger,
228
- schemaConfigDeliveryEndpoint: mockCloudConfigUrl,
233
+ uplinkEndpoints: [mockCloudConfigUrl1],
234
+ uplinkMaxRetries: 0
229
235
  });
230
236
  // @ts-ignore for testing purposes, a short pollInterval is ideal so we'll override here
231
237
  gateway.experimental_pollInterval = 100;
@@ -242,7 +248,7 @@ describe('Supergraph SDL update failures', () => {
242
248
 
243
249
  it("Doesn't update and logs on receiving unparseable Supergraph SDL", async () => {
244
250
  mockSupergraphSdlRequestSuccess();
245
- mockSupergraphSdlRequest().reply(
251
+ mockSupergraphSdlRequestIfAfter('originalId-1234').reply(
246
252
  200,
247
253
  JSON.stringify({
248
254
  data: {
@@ -262,7 +268,7 @@ describe('Supergraph SDL update failures', () => {
262
268
 
263
269
  gateway = new ApolloGateway({
264
270
  logger,
265
- schemaConfigDeliveryEndpoint: mockCloudConfigUrl,
271
+ uplinkEndpoints: [mockCloudConfigUrl1],
266
272
  });
267
273
  // @ts-ignore for testing purposes, a short pollInterval is ideal so we'll override here
268
274
  gateway.experimental_pollInterval = 100;
@@ -292,7 +298,7 @@ describe('Supergraph SDL update failures', () => {
292
298
 
293
299
  gateway = new ApolloGateway({
294
300
  logger,
295
- schemaConfigDeliveryEndpoint: mockCloudConfigUrl,
301
+ uplinkEndpoints: [mockCloudConfigUrl1],
296
302
  });
297
303
  // @ts-ignore for testing purposes, a short pollInterval is ideal so we'll override here
298
304
  gateway.experimental_pollInterval = 100;
@@ -314,8 +320,12 @@ describe('Supergraph SDL update failures', () => {
314
320
  it('Rollsback to a previous schema when triggered', async () => {
315
321
  // Init
316
322
  mockSupergraphSdlRequestSuccess();
317
- mockSupergraphSdlRequestSuccess(getTestingSupergraphSdl(fixturesWithUpdate), 'updatedId-5678');
318
- mockSupergraphSdlRequestSuccess();
323
+ mockSupergraphSdlRequestSuccessIfAfter(
324
+ 'originalId-1234',
325
+ 'updatedId-5678',
326
+ getTestingSupergraphSdl(fixturesWithUpdate),
327
+ );
328
+ mockSupergraphSdlRequestSuccessIfAfter('updatedId-5678');
319
329
 
320
330
  let firstResolve: Function;
321
331
  let secondResolve: Function;
@@ -332,7 +342,7 @@ it('Rollsback to a previous schema when triggered', async () => {
332
342
 
333
343
  gateway = new ApolloGateway({
334
344
  logger,
335
- schemaConfigDeliveryEndpoint: mockCloudConfigUrl,
345
+ uplinkEndpoints: [mockCloudConfigUrl1],
336
346
  });
337
347
  // @ts-ignore for testing purposes, a short pollInterval is ideal so we'll override here
338
348
  gateway.experimental_pollInterval = 100;
@@ -416,7 +426,7 @@ describe('Downstream service health checks', () => {
416
426
  gateway = new ApolloGateway({
417
427
  serviceHealthCheck: true,
418
428
  logger,
419
- schemaConfigDeliveryEndpoint: mockCloudConfigUrl,
429
+ uplinkEndpoints: [mockCloudConfigUrl1],
420
430
  });
421
431
  // @ts-ignore for testing purposes, a short pollInterval is ideal so we'll override here
422
432
  gateway.experimental_pollInterval = 100;
@@ -439,7 +449,7 @@ describe('Downstream service health checks', () => {
439
449
  gateway = new ApolloGateway({
440
450
  serviceHealthCheck: true,
441
451
  logger,
442
- schemaConfigDeliveryEndpoint: mockCloudConfigUrl,
452
+ uplinkEndpoints: [mockCloudConfigUrl1],
443
453
  });
444
454
 
445
455
  // This is the ideal, but our version of Jest has a bug with printing error snapshots.
@@ -480,9 +490,10 @@ describe('Downstream service health checks', () => {
480
490
  mockAllServicesHealthCheckSuccess();
481
491
 
482
492
  // Update
483
- mockSupergraphSdlRequestSuccess(
484
- getTestingSupergraphSdl(fixturesWithUpdate),
493
+ mockSupergraphSdlRequestSuccessIfAfter(
494
+ 'originalId-1234',
485
495
  'updatedId-5678',
496
+ getTestingSupergraphSdl(fixturesWithUpdate),
486
497
  );
487
498
  mockAllServicesHealthCheckSuccess();
488
499
 
@@ -498,7 +509,7 @@ describe('Downstream service health checks', () => {
498
509
  gateway = new ApolloGateway({
499
510
  serviceHealthCheck: true,
500
511
  logger,
501
- schemaConfigDeliveryEndpoint: mockCloudConfigUrl,
512
+ uplinkEndpoints: [mockCloudConfigUrl1],
502
513
  });
503
514
  // @ts-ignore for testing purposes, a short pollInterval is ideal so we'll override here
504
515
  gateway.experimental_pollInterval = 100;
@@ -523,9 +534,10 @@ describe('Downstream service health checks', () => {
523
534
  mockAllServicesHealthCheckSuccess();
524
535
 
525
536
  // Update (with one health check failure)
526
- mockSupergraphSdlRequestSuccess(
527
- getTestingSupergraphSdl(fixturesWithUpdate),
537
+ mockSupergraphSdlRequestSuccessIfAfter(
538
+ 'originalId-1234',
528
539
  'updatedId-5678',
540
+ getTestingSupergraphSdl(fixturesWithUpdate),
529
541
  );
530
542
  mockServiceHealthCheck(accounts).reply(500);
531
543
  mockServiceHealthCheckSuccess(books);
@@ -540,7 +552,7 @@ describe('Downstream service health checks', () => {
540
552
  gateway = new ApolloGateway({
541
553
  serviceHealthCheck: true,
542
554
  logger,
543
- schemaConfigDeliveryEndpoint: mockCloudConfigUrl,
555
+ uplinkEndpoints: [mockCloudConfigUrl1],
544
556
  });
545
557
  // @ts-ignore for testing purposes, a short pollInterval is ideal so we'll override here
546
558
  gateway.experimental_pollInterval = 100;
@@ -64,27 +64,42 @@ function gatewayNock(url: Parameters<typeof nock>[0]): nock.Scope {
64
64
  });
65
65
  }
66
66
 
67
- export const mockCloudConfigUrl =
68
- 'https://example.cloud-config-url.com/cloudconfig/';
67
+ export const mockCloudConfigUrl1 =
68
+ 'https://example1.cloud-config-url.com/cloudconfig/';
69
+
70
+ export const mockCloudConfigUrl2 =
71
+ 'https://example2.cloud-config-url.com/cloudconfig/';
72
+
73
+ export const mockCloudConfigUrl3 =
74
+ 'https://example3.cloud-config-url.com/cloudconfig/';
69
75
 
70
76
  export const mockOutOfBandReporterUrl =
71
77
  'https://example.outofbandreporter.com/monitoring/';
72
78
 
73
- export function mockSupergraphSdlRequest() {
74
- return gatewayNock(mockCloudConfigUrl).post('/', {
79
+ export function mockSupergraphSdlRequestIfAfter(ifAfter: string | null, url: string = mockCloudConfigUrl1) {
80
+ return gatewayNock(url).post('/', {
75
81
  query: SUPERGRAPH_SDL_QUERY,
76
82
  variables: {
77
83
  ref: graphRef,
78
84
  apiKey: apiKey,
85
+ ifAfterId: ifAfter,
79
86
  },
80
87
  });
81
88
  }
82
89
 
83
- export function mockSupergraphSdlRequestSuccess(
84
- supergraphSdl = getTestingSupergraphSdl(),
85
- id = 'originalId-1234',
90
+ export function mockSupergraphSdlRequest(ifAfter: string | null = null, url: string = mockCloudConfigUrl1) {
91
+ return mockSupergraphSdlRequestIfAfter(ifAfter, url);
92
+ }
93
+
94
+ export function mockSupergraphSdlRequestSuccessIfAfter(
95
+ ifAfter: string | null = null,
96
+ id: string = 'originalId-1234',
97
+ supergraphSdl: string = getTestingSupergraphSdl(),
86
98
  ) {
87
- return mockSupergraphSdlRequest().reply(
99
+ if (supergraphSdl == null) {
100
+ supergraphSdl = getTestingSupergraphSdl();
101
+ }
102
+ return mockSupergraphSdlRequestIfAfter(ifAfter).reply(
88
103
  200,
89
104
  JSON.stringify({
90
105
  data: {
@@ -98,6 +113,25 @@ export function mockSupergraphSdlRequestSuccess(
98
113
  );
99
114
  }
100
115
 
116
+ export function mockSupergraphSdlRequestIfAfterUnchanged(
117
+ ifAfter: string | null = null,
118
+ ) {
119
+ return mockSupergraphSdlRequestIfAfter(ifAfter).reply(
120
+ 200,
121
+ JSON.stringify({
122
+ data: {
123
+ routerConfig: {
124
+ __typename: 'Unchanged',
125
+ },
126
+ },
127
+ }),
128
+ );
129
+ }
130
+
131
+ export function mockSupergraphSdlRequestSuccess() {
132
+ return mockSupergraphSdlRequestSuccessIfAfter(null);
133
+ }
134
+
101
135
  export function mockOutOfBandReportRequest() {
102
136
  return gatewayNock(mockOutOfBandReporterUrl).post('/', () => true);
103
137
  }