@apollo/gateway 2.0.2-alpha.1 → 2.0.2-alpha.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/dist/config.d.ts +2 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/datasources/RemoteGraphQLDataSource.d.ts +6 -5
- package/dist/datasources/RemoteGraphQLDataSource.d.ts.map +1 -1
- package/dist/datasources/RemoteGraphQLDataSource.js +16 -11
- package/dist/datasources/RemoteGraphQLDataSource.js.map +1 -1
- package/dist/executeQueryPlan.d.ts.map +1 -1
- package/dist/executeQueryPlan.js +2 -2
- package/dist/executeQueryPlan.js.map +1 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -20
- package/dist/index.js.map +1 -1
- package/dist/supergraphManagers/UplinkFetcher/index.d.ts +2 -2
- package/dist/supergraphManagers/UplinkFetcher/index.d.ts.map +1 -1
- package/dist/supergraphManagers/UplinkFetcher/index.js.map +1 -1
- package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.d.ts +3 -3
- package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.d.ts.map +1 -1
- package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.js +14 -13
- package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.js.map +1 -1
- package/dist/supergraphManagers/UplinkFetcher/outOfBandReporter.d.ts +6 -5
- package/dist/supergraphManagers/UplinkFetcher/outOfBandReporter.d.ts.map +1 -1
- package/dist/supergraphManagers/UplinkFetcher/outOfBandReporter.js +3 -3
- package/dist/supergraphManagers/UplinkFetcher/outOfBandReporter.js.map +1 -1
- package/package.json +7 -7
- package/src/__tests__/gateway/buildService.test.ts +81 -83
- package/src/__tests__/gateway/executor.test.ts +20 -17
- package/src/__tests__/gateway/opentelemetry.test.ts +3 -7
- package/src/__tests__/gateway/supergraphSdl.test.ts +6 -11
- package/src/config.ts +2 -2
- package/src/datasources/RemoteGraphQLDataSource.ts +32 -16
- package/src/datasources/__tests__/RemoteGraphQLDataSource.test.ts +106 -140
- package/src/executeQueryPlan.ts +5 -1
- package/src/index.ts +3 -26
- package/src/supergraphManagers/IntrospectAndCompose/__tests__/IntrospectAndCompose.test.ts +0 -6
- package/src/supergraphManagers/UplinkFetcher/__tests__/loadSupergraphSdlFromStorage.test.ts +70 -74
- package/src/supergraphManagers/UplinkFetcher/index.ts +2 -2
- package/src/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.ts +23 -17
- package/src/supergraphManagers/UplinkFetcher/outOfBandReporter.ts +9 -7
- package/src/__mocks__/apollo-server-env.ts +0 -56
- package/src/__mocks__/make-fetch-happen-fetcher.ts +0 -57
- package/src/make-fetch-happen.d.ts +0 -59
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
loadSupergraphSdlFromUplinks,
|
|
4
4
|
UplinkFetcherError,
|
|
5
5
|
} from '../loadSupergraphSdlFromStorage';
|
|
6
|
-
import
|
|
6
|
+
import fetcher from 'make-fetch-happen';
|
|
7
7
|
import {
|
|
8
8
|
graphRef,
|
|
9
9
|
apiKey,
|
|
@@ -14,10 +14,13 @@ import {
|
|
|
14
14
|
mockOutOfBandReportRequestSuccess,
|
|
15
15
|
mockSupergraphSdlRequestSuccess,
|
|
16
16
|
mockSupergraphSdlRequestIfAfterUnchanged,
|
|
17
|
-
mockSupergraphSdlRequestIfAfter
|
|
17
|
+
mockSupergraphSdlRequestIfAfter,
|
|
18
18
|
} from '../../../__tests__/integration/nockMocks';
|
|
19
|
-
import { getTestingSupergraphSdl } from
|
|
20
|
-
import {
|
|
19
|
+
import { getTestingSupergraphSdl } from '../../../__tests__/execution-utils';
|
|
20
|
+
import {
|
|
21
|
+
nockAfterEach,
|
|
22
|
+
nockBeforeEach,
|
|
23
|
+
} from '../../../__tests__/nockAssertions';
|
|
21
24
|
|
|
22
25
|
describe('loadSupergraphSdlFromStorage', () => {
|
|
23
26
|
beforeEach(nockBeforeEach);
|
|
@@ -25,7 +28,6 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
25
28
|
|
|
26
29
|
it('fetches Supergraph SDL as expected', async () => {
|
|
27
30
|
mockSupergraphSdlRequestSuccess();
|
|
28
|
-
const fetcher = getDefaultFetcher();
|
|
29
31
|
const result = await loadSupergraphSdlFromStorage({
|
|
30
32
|
graphRef,
|
|
31
33
|
apiKey,
|
|
@@ -42,27 +44,29 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
42
44
|
|
|
43
45
|
it('Queries alternate Uplink URL if first one fails', async () => {
|
|
44
46
|
mockSupergraphSdlRequest('originalId-1234', mockCloudConfigUrl1).reply(500);
|
|
45
|
-
mockSupergraphSdlRequestIfAfter(
|
|
47
|
+
mockSupergraphSdlRequestIfAfter(
|
|
48
|
+
'originalId-1234',
|
|
49
|
+
mockCloudConfigUrl2,
|
|
50
|
+
).reply(
|
|
46
51
|
200,
|
|
47
52
|
JSON.stringify({
|
|
48
53
|
data: {
|
|
49
54
|
routerConfig: {
|
|
50
55
|
__typename: 'RouterConfigResult',
|
|
51
56
|
id: 'originalId-1234',
|
|
52
|
-
supergraphSdl: getTestingSupergraphSdl()
|
|
57
|
+
supergraphSdl: getTestingSupergraphSdl(),
|
|
53
58
|
},
|
|
54
59
|
},
|
|
55
60
|
}),
|
|
56
61
|
);
|
|
57
62
|
|
|
58
|
-
const fetcher = getDefaultFetcher();
|
|
59
63
|
const result = await loadSupergraphSdlFromUplinks({
|
|
60
64
|
graphRef,
|
|
61
65
|
apiKey,
|
|
62
66
|
endpoints: [mockCloudConfigUrl1, mockCloudConfigUrl2],
|
|
63
67
|
errorReportingEndpoint: undefined,
|
|
64
68
|
fetcher,
|
|
65
|
-
compositionId:
|
|
69
|
+
compositionId: 'originalId-1234',
|
|
66
70
|
maxRetries: 1,
|
|
67
71
|
roundRobinSeed: 0,
|
|
68
72
|
earliestFetchTime: null,
|
|
@@ -75,10 +79,12 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
75
79
|
});
|
|
76
80
|
|
|
77
81
|
it('Throws error if all Uplink URLs fail', async () => {
|
|
78
|
-
mockSupergraphSdlRequest(
|
|
79
|
-
mockSupergraphSdlRequestIfAfter(
|
|
82
|
+
mockSupergraphSdlRequest('originalId-1234', mockCloudConfigUrl1).reply(500);
|
|
83
|
+
mockSupergraphSdlRequestIfAfter(
|
|
84
|
+
'originalId-1234',
|
|
85
|
+
mockCloudConfigUrl2,
|
|
86
|
+
).reply(500);
|
|
80
87
|
|
|
81
|
-
const fetcher = getDefaultFetcher();
|
|
82
88
|
await expect(
|
|
83
89
|
loadSupergraphSdlFromUplinks({
|
|
84
90
|
graphRef,
|
|
@@ -86,23 +92,22 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
86
92
|
endpoints: [mockCloudConfigUrl1, mockCloudConfigUrl2],
|
|
87
93
|
errorReportingEndpoint: undefined,
|
|
88
94
|
fetcher,
|
|
89
|
-
compositionId:
|
|
95
|
+
compositionId: 'originalId-1234',
|
|
90
96
|
maxRetries: 1,
|
|
91
97
|
roundRobinSeed: 0,
|
|
92
98
|
earliestFetchTime: null,
|
|
93
99
|
}),
|
|
94
100
|
).rejects.toThrowError(
|
|
95
101
|
new UplinkFetcherError(
|
|
96
|
-
|
|
97
|
-
)
|
|
102
|
+
'An error occurred while fetching your schema from Apollo: 500 Internal Server Error',
|
|
103
|
+
),
|
|
98
104
|
);
|
|
99
|
-
})
|
|
105
|
+
});
|
|
100
106
|
|
|
101
107
|
describe('errors', () => {
|
|
102
108
|
it('throws on a malformed response', async () => {
|
|
103
109
|
mockSupergraphSdlRequest().reply(200, 'Invalid JSON');
|
|
104
110
|
|
|
105
|
-
const fetcher = getDefaultFetcher();
|
|
106
111
|
await expect(
|
|
107
112
|
loadSupergraphSdlFromStorage({
|
|
108
113
|
graphRef,
|
|
@@ -114,8 +119,8 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
114
119
|
}),
|
|
115
120
|
).rejects.toThrowError(
|
|
116
121
|
new UplinkFetcherError(
|
|
117
|
-
|
|
118
|
-
)
|
|
122
|
+
'An error occurred while fetching your schema from Apollo: 200 invalid json response body at https://example1.cloud-config-url.com/cloudconfig/ reason: Unexpected token I in JSON at position 0',
|
|
123
|
+
),
|
|
119
124
|
);
|
|
120
125
|
});
|
|
121
126
|
|
|
@@ -128,7 +133,6 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
128
133
|
}),
|
|
129
134
|
);
|
|
130
135
|
|
|
131
|
-
const fetcher = getDefaultFetcher();
|
|
132
136
|
await expect(
|
|
133
137
|
loadSupergraphSdlFromStorage({
|
|
134
138
|
graphRef,
|
|
@@ -139,7 +143,9 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
139
143
|
compositionId: null,
|
|
140
144
|
}),
|
|
141
145
|
).rejects.toThrowError(
|
|
142
|
-
new UplinkFetcherError(
|
|
146
|
+
new UplinkFetcherError(
|
|
147
|
+
`An error occurred while fetching your schema from Apollo: \n${message}`,
|
|
148
|
+
),
|
|
143
149
|
);
|
|
144
150
|
});
|
|
145
151
|
|
|
@@ -147,7 +153,6 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
147
153
|
mockSupergraphSdlRequest().reply(500);
|
|
148
154
|
mockOutOfBandReportRequestSuccess();
|
|
149
155
|
|
|
150
|
-
const fetcher = getDefaultFetcher();
|
|
151
156
|
await expect(
|
|
152
157
|
loadSupergraphSdlFromStorage({
|
|
153
158
|
graphRef,
|
|
@@ -159,8 +164,8 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
159
164
|
}),
|
|
160
165
|
).rejects.toThrowError(
|
|
161
166
|
new UplinkFetcherError(
|
|
162
|
-
|
|
163
|
-
)
|
|
167
|
+
'An error occurred while fetching your schema from Apollo: 500 Internal Server Error',
|
|
168
|
+
),
|
|
164
169
|
);
|
|
165
170
|
});
|
|
166
171
|
|
|
@@ -169,7 +174,6 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
169
174
|
it("Out of band reporting doesn't submit reports when endpoint is not configured", async () => {
|
|
170
175
|
mockSupergraphSdlRequest().reply(400);
|
|
171
176
|
|
|
172
|
-
const fetcher = getDefaultFetcher();
|
|
173
177
|
await expect(
|
|
174
178
|
loadSupergraphSdlFromStorage({
|
|
175
179
|
graphRef,
|
|
@@ -181,16 +185,14 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
181
185
|
}),
|
|
182
186
|
).rejects.toThrowError(
|
|
183
187
|
new UplinkFetcherError(
|
|
184
|
-
|
|
185
|
-
)
|
|
188
|
+
'An error occurred while fetching your schema from Apollo: 400 invalid json response body at https://example1.cloud-config-url.com/cloudconfig/ reason: Unexpected end of JSON input',
|
|
189
|
+
),
|
|
186
190
|
);
|
|
187
191
|
});
|
|
188
192
|
|
|
189
193
|
it('throws on 400 status response and does not submit an out of band error', async () => {
|
|
190
|
-
|
|
191
194
|
mockSupergraphSdlRequest().reply(400);
|
|
192
195
|
|
|
193
|
-
const fetcher = getDefaultFetcher();
|
|
194
196
|
await expect(
|
|
195
197
|
loadSupergraphSdlFromStorage({
|
|
196
198
|
graphRef,
|
|
@@ -202,8 +204,8 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
202
204
|
}),
|
|
203
205
|
).rejects.toThrowError(
|
|
204
206
|
new UplinkFetcherError(
|
|
205
|
-
|
|
206
|
-
)
|
|
207
|
+
'An error occurred while fetching your schema from Apollo: 400 invalid json response body at https://example1.cloud-config-url.com/cloudconfig/ reason: Unexpected end of JSON input',
|
|
208
|
+
),
|
|
207
209
|
);
|
|
208
210
|
});
|
|
209
211
|
|
|
@@ -211,7 +213,6 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
211
213
|
mockSupergraphSdlRequest().reply(413);
|
|
212
214
|
mockOutOfBandReportRequestSuccess();
|
|
213
215
|
|
|
214
|
-
const fetcher = getDefaultFetcher();
|
|
215
216
|
await expect(
|
|
216
217
|
loadSupergraphSdlFromStorage({
|
|
217
218
|
graphRef,
|
|
@@ -223,8 +224,8 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
223
224
|
}),
|
|
224
225
|
).rejects.toThrowError(
|
|
225
226
|
new UplinkFetcherError(
|
|
226
|
-
|
|
227
|
-
)
|
|
227
|
+
'An error occurred while fetching your schema from Apollo: 413 Payload Too Large',
|
|
228
|
+
),
|
|
228
229
|
);
|
|
229
230
|
});
|
|
230
231
|
|
|
@@ -232,7 +233,6 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
232
233
|
mockSupergraphSdlRequest().reply(422);
|
|
233
234
|
mockOutOfBandReportRequestSuccess();
|
|
234
235
|
|
|
235
|
-
const fetcher = getDefaultFetcher();
|
|
236
236
|
await expect(
|
|
237
237
|
loadSupergraphSdlFromStorage({
|
|
238
238
|
graphRef,
|
|
@@ -244,8 +244,8 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
244
244
|
}),
|
|
245
245
|
).rejects.toThrowError(
|
|
246
246
|
new UplinkFetcherError(
|
|
247
|
-
|
|
248
|
-
)
|
|
247
|
+
'An error occurred while fetching your schema from Apollo: 422 Unprocessable Entity',
|
|
248
|
+
),
|
|
249
249
|
);
|
|
250
250
|
});
|
|
251
251
|
|
|
@@ -253,7 +253,6 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
253
253
|
mockSupergraphSdlRequest().reply(408);
|
|
254
254
|
mockOutOfBandReportRequestSuccess();
|
|
255
255
|
|
|
256
|
-
const fetcher = getDefaultFetcher();
|
|
257
256
|
await expect(
|
|
258
257
|
loadSupergraphSdlFromStorage({
|
|
259
258
|
graphRef,
|
|
@@ -265,18 +264,16 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
265
264
|
}),
|
|
266
265
|
).rejects.toThrowError(
|
|
267
266
|
new UplinkFetcherError(
|
|
268
|
-
|
|
269
|
-
)
|
|
267
|
+
'An error occurred while fetching your schema from Apollo: 408 Request Timeout',
|
|
268
|
+
),
|
|
270
269
|
);
|
|
271
270
|
});
|
|
272
271
|
});
|
|
273
272
|
|
|
274
273
|
it('throws on 504 status response and successfully submits an out of band error', async () => {
|
|
275
|
-
|
|
276
274
|
mockSupergraphSdlRequest().reply(504);
|
|
277
275
|
mockOutOfBandReportRequestSuccess();
|
|
278
276
|
|
|
279
|
-
const fetcher = getDefaultFetcher();
|
|
280
277
|
await expect(
|
|
281
278
|
loadSupergraphSdlFromStorage({
|
|
282
279
|
graphRef,
|
|
@@ -288,8 +285,8 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
288
285
|
}),
|
|
289
286
|
).rejects.toThrowError(
|
|
290
287
|
new UplinkFetcherError(
|
|
291
|
-
|
|
292
|
-
)
|
|
288
|
+
'An error occurred while fetching your schema from Apollo: 504 Gateway Timeout',
|
|
289
|
+
),
|
|
293
290
|
);
|
|
294
291
|
});
|
|
295
292
|
|
|
@@ -297,7 +294,6 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
297
294
|
mockSupergraphSdlRequest().replyWithError('no response');
|
|
298
295
|
mockOutOfBandReportRequestSuccess();
|
|
299
296
|
|
|
300
|
-
const fetcher = getDefaultFetcher();
|
|
301
297
|
await expect(
|
|
302
298
|
loadSupergraphSdlFromStorage({
|
|
303
299
|
graphRef,
|
|
@@ -309,8 +305,8 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
309
305
|
}),
|
|
310
306
|
).rejects.toThrowError(
|
|
311
307
|
new UplinkFetcherError(
|
|
312
|
-
|
|
313
|
-
)
|
|
308
|
+
'An error occurred while fetching your schema from Apollo: request to https://example1.cloud-config-url.com/cloudconfig/ failed, reason: no response',
|
|
309
|
+
),
|
|
314
310
|
);
|
|
315
311
|
});
|
|
316
312
|
|
|
@@ -318,7 +314,6 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
318
314
|
mockSupergraphSdlRequest().reply(502);
|
|
319
315
|
mockOutOfBandReportRequestSuccess();
|
|
320
316
|
|
|
321
|
-
const fetcher = getDefaultFetcher();
|
|
322
317
|
await expect(
|
|
323
318
|
loadSupergraphSdlFromStorage({
|
|
324
319
|
graphRef,
|
|
@@ -330,8 +325,8 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
330
325
|
}),
|
|
331
326
|
).rejects.toThrowError(
|
|
332
327
|
new UplinkFetcherError(
|
|
333
|
-
|
|
334
|
-
)
|
|
328
|
+
'An error occurred while fetching your schema from Apollo: 502 Bad Gateway',
|
|
329
|
+
),
|
|
335
330
|
);
|
|
336
331
|
});
|
|
337
332
|
|
|
@@ -339,7 +334,6 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
339
334
|
mockSupergraphSdlRequest().reply(503);
|
|
340
335
|
mockOutOfBandReportRequestSuccess();
|
|
341
336
|
|
|
342
|
-
const fetcher = getDefaultFetcher();
|
|
343
337
|
await expect(
|
|
344
338
|
loadSupergraphSdlFromStorage({
|
|
345
339
|
graphRef,
|
|
@@ -351,69 +345,72 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
351
345
|
}),
|
|
352
346
|
).rejects.toThrowError(
|
|
353
347
|
new UplinkFetcherError(
|
|
354
|
-
|
|
355
|
-
)
|
|
348
|
+
'An error occurred while fetching your schema from Apollo: 503 Service Unavailable',
|
|
349
|
+
),
|
|
356
350
|
);
|
|
357
351
|
});
|
|
358
352
|
|
|
359
353
|
it('successfully responds to SDL unchanged by returning null', async () => {
|
|
360
|
-
mockSupergraphSdlRequestIfAfterUnchanged(
|
|
354
|
+
mockSupergraphSdlRequestIfAfterUnchanged('id-1234');
|
|
361
355
|
|
|
362
|
-
const fetcher = getDefaultFetcher();
|
|
363
356
|
const result = await loadSupergraphSdlFromStorage({
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
357
|
+
graphRef,
|
|
358
|
+
apiKey,
|
|
359
|
+
endpoint: mockCloudConfigUrl1,
|
|
360
|
+
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
361
|
+
fetcher,
|
|
362
|
+
compositionId: 'id-1234',
|
|
370
363
|
});
|
|
371
364
|
expect(result).toBeNull();
|
|
372
365
|
});
|
|
373
366
|
});
|
|
374
367
|
|
|
375
|
-
|
|
376
|
-
describe("loadSupergraphSdlFromUplinks", () => {
|
|
368
|
+
describe('loadSupergraphSdlFromUplinks', () => {
|
|
377
369
|
beforeEach(nockBeforeEach);
|
|
378
370
|
afterEach(nockAfterEach);
|
|
379
371
|
|
|
380
372
|
it("doesn't retry in the unchanged / null case", async () => {
|
|
381
|
-
mockSupergraphSdlRequestIfAfterUnchanged(
|
|
373
|
+
mockSupergraphSdlRequestIfAfterUnchanged('id-1234', mockCloudConfigUrl1);
|
|
382
374
|
|
|
383
|
-
|
|
375
|
+
let calls = 0;
|
|
384
376
|
const result = await loadSupergraphSdlFromUplinks({
|
|
385
377
|
graphRef,
|
|
386
378
|
apiKey,
|
|
387
379
|
endpoints: [mockCloudConfigUrl1, mockCloudConfigUrl2],
|
|
388
380
|
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
389
|
-
fetcher:
|
|
390
|
-
|
|
381
|
+
fetcher: (...args) => {
|
|
382
|
+
calls++;
|
|
383
|
+
return fetcher(...args);
|
|
384
|
+
},
|
|
385
|
+
compositionId: 'id-1234',
|
|
391
386
|
maxRetries: 5,
|
|
392
387
|
roundRobinSeed: 0,
|
|
393
388
|
earliestFetchTime: null,
|
|
394
389
|
});
|
|
395
390
|
|
|
396
391
|
expect(result).toBeNull();
|
|
397
|
-
expect(
|
|
392
|
+
expect(calls).toBe(1);
|
|
398
393
|
});
|
|
399
394
|
|
|
400
|
-
it(
|
|
395
|
+
it('Waits the correct time before retrying', async () => {
|
|
401
396
|
const timeoutSpy = jest.spyOn(global, 'setTimeout');
|
|
402
397
|
|
|
403
398
|
mockSupergraphSdlRequest('originalId-1234', mockCloudConfigUrl1).reply(500);
|
|
404
|
-
mockSupergraphSdlRequestIfAfter(
|
|
399
|
+
mockSupergraphSdlRequestIfAfter(
|
|
400
|
+
'originalId-1234',
|
|
401
|
+
mockCloudConfigUrl2,
|
|
402
|
+
).reply(
|
|
405
403
|
200,
|
|
406
404
|
JSON.stringify({
|
|
407
405
|
data: {
|
|
408
406
|
routerConfig: {
|
|
409
407
|
__typename: 'RouterConfigResult',
|
|
410
408
|
id: 'originalId-1234',
|
|
411
|
-
supergraphSdl: getTestingSupergraphSdl()
|
|
409
|
+
supergraphSdl: getTestingSupergraphSdl(),
|
|
412
410
|
},
|
|
413
411
|
},
|
|
414
412
|
}),
|
|
415
413
|
);
|
|
416
|
-
const fetcher = getDefaultFetcher();
|
|
417
414
|
|
|
418
415
|
await loadSupergraphSdlFromUplinks({
|
|
419
416
|
graphRef,
|
|
@@ -421,7 +418,7 @@ describe("loadSupergraphSdlFromUplinks", () => {
|
|
|
421
418
|
endpoints: [mockCloudConfigUrl1, mockCloudConfigUrl2],
|
|
422
419
|
errorReportingEndpoint: undefined,
|
|
423
420
|
fetcher: fetcher,
|
|
424
|
-
compositionId:
|
|
421
|
+
compositionId: 'originalId-1234',
|
|
425
422
|
maxRetries: 1,
|
|
426
423
|
roundRobinSeed: 0,
|
|
427
424
|
earliestFetchTime: new Date(Date.now() + 1000),
|
|
@@ -435,4 +432,3 @@ describe("loadSupergraphSdlFromUplinks", () => {
|
|
|
435
432
|
timeoutSpy.mockRestore();
|
|
436
433
|
});
|
|
437
434
|
});
|
|
438
|
-
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { fetch } from 'apollo-server-env';
|
|
2
1
|
import type { Logger } from '@apollo/utils.logger';
|
|
3
2
|
import resolvable from '@josephg/resolvable';
|
|
4
3
|
import { SupergraphManager, SupergraphSdlHookOptions } from '../../config';
|
|
5
4
|
import { SubgraphHealthCheckFunction, SupergraphSdlUpdateFunction } from '../..';
|
|
6
5
|
import { loadSupergraphSdlFromUplinks } from './loadSupergraphSdlFromStorage';
|
|
6
|
+
import { Fetcher } from '@apollo/utils.fetcher';
|
|
7
7
|
|
|
8
8
|
export interface UplinkFetcherOptions {
|
|
9
9
|
fallbackPollIntervalInMs: number;
|
|
10
10
|
subgraphHealthCheck?: boolean;
|
|
11
11
|
graphRef: string;
|
|
12
12
|
apiKey: string;
|
|
13
|
-
fetcher:
|
|
13
|
+
fetcher: Fetcher;
|
|
14
14
|
maxRetries: number;
|
|
15
15
|
uplinkEndpoints: string[];
|
|
16
16
|
logger?: Logger;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { fetch, Response, Request } from 'apollo-server-env';
|
|
2
1
|
import { GraphQLError } from 'graphql';
|
|
3
2
|
import retry from 'async-retry';
|
|
4
3
|
import { SupergraphSdlUpdate } from '../../config';
|
|
5
4
|
import { submitOutOfBandReportIfConfigured } from './outOfBandReporter';
|
|
6
5
|
import { SupergraphSdlQuery } from '../../__generated__/graphqlTypes';
|
|
6
|
+
import type {
|
|
7
|
+
Fetcher,
|
|
8
|
+
FetcherResponse,
|
|
9
|
+
FetcherRequestInit,
|
|
10
|
+
} from '@apollo/utils.fetcher';
|
|
7
11
|
|
|
8
12
|
// Magic /* GraphQL */ comment below is for codegen, do not remove
|
|
9
13
|
export const SUPERGRAPH_SDL_QUERY = /* GraphQL */`#graphql
|
|
@@ -63,7 +67,7 @@ export async function loadSupergraphSdlFromUplinks({
|
|
|
63
67
|
apiKey: string;
|
|
64
68
|
endpoints: string[];
|
|
65
69
|
errorReportingEndpoint: string | undefined,
|
|
66
|
-
fetcher:
|
|
70
|
+
fetcher: Fetcher;
|
|
67
71
|
compositionId: string | null;
|
|
68
72
|
maxRetries: number,
|
|
69
73
|
roundRobinSeed: number,
|
|
@@ -105,20 +109,21 @@ export async function loadSupergraphSdlFromStorage({
|
|
|
105
109
|
apiKey: string;
|
|
106
110
|
endpoint: string;
|
|
107
111
|
errorReportingEndpoint?: string;
|
|
108
|
-
fetcher:
|
|
112
|
+
fetcher: Fetcher;
|
|
109
113
|
compositionId: string | null;
|
|
110
114
|
}) : Promise<SupergraphSdlUpdate | null> {
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
const requestBody = JSON.stringify({
|
|
116
|
+
query: SUPERGRAPH_SDL_QUERY,
|
|
117
|
+
variables: {
|
|
118
|
+
ref: graphRef,
|
|
119
|
+
apiKey,
|
|
120
|
+
ifAfterId: compositionId,
|
|
121
|
+
},
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
const requestDetails: FetcherRequestInit = {
|
|
113
125
|
method: 'POST',
|
|
114
|
-
body:
|
|
115
|
-
query: SUPERGRAPH_SDL_QUERY,
|
|
116
|
-
variables: {
|
|
117
|
-
ref: graphRef,
|
|
118
|
-
apiKey,
|
|
119
|
-
ifAfterId: compositionId,
|
|
120
|
-
},
|
|
121
|
-
}),
|
|
126
|
+
body: requestBody,
|
|
122
127
|
headers: {
|
|
123
128
|
'apollographql-client-name': name,
|
|
124
129
|
'apollographql-client-version': version,
|
|
@@ -127,9 +132,8 @@ export async function loadSupergraphSdlFromStorage({
|
|
|
127
132
|
},
|
|
128
133
|
};
|
|
129
134
|
|
|
130
|
-
const request: Request = new Request(endpoint, requestDetails);
|
|
131
|
-
|
|
132
135
|
const startTime = new Date();
|
|
136
|
+
let result: FetcherResponse;
|
|
133
137
|
try {
|
|
134
138
|
result = await fetcher(endpoint, requestDetails);
|
|
135
139
|
} catch (e) {
|
|
@@ -137,7 +141,8 @@ export async function loadSupergraphSdlFromStorage({
|
|
|
137
141
|
|
|
138
142
|
await submitOutOfBandReportIfConfigured({
|
|
139
143
|
error: e,
|
|
140
|
-
|
|
144
|
+
requestEndpoint: endpoint,
|
|
145
|
+
requestBody,
|
|
141
146
|
endpoint: errorReportingEndpoint,
|
|
142
147
|
startedAt: startTime,
|
|
143
148
|
endedAt: endTime,
|
|
@@ -168,7 +173,8 @@ export async function loadSupergraphSdlFromStorage({
|
|
|
168
173
|
} else {
|
|
169
174
|
await submitOutOfBandReportIfConfigured({
|
|
170
175
|
error: new UplinkFetcherError(fetchErrorMsg + result.status + ' ' + result.statusText),
|
|
171
|
-
|
|
176
|
+
requestEndpoint: endpoint,
|
|
177
|
+
requestBody,
|
|
172
178
|
endpoint: errorReportingEndpoint,
|
|
173
179
|
response: result,
|
|
174
180
|
startedAt: startTime,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fetcher, FetcherResponse } from '@apollo/utils.fetcher';
|
|
2
2
|
import { GraphQLError } from 'graphql';
|
|
3
3
|
import {
|
|
4
4
|
ErrorCode,
|
|
@@ -30,7 +30,8 @@ interface OobReportMutationFailure {
|
|
|
30
30
|
|
|
31
31
|
export async function submitOutOfBandReportIfConfigured({
|
|
32
32
|
error,
|
|
33
|
-
|
|
33
|
+
requestEndpoint,
|
|
34
|
+
requestBody,
|
|
34
35
|
endpoint,
|
|
35
36
|
response,
|
|
36
37
|
startedAt,
|
|
@@ -39,13 +40,14 @@ export async function submitOutOfBandReportIfConfigured({
|
|
|
39
40
|
fetcher,
|
|
40
41
|
}: {
|
|
41
42
|
error: Error;
|
|
42
|
-
|
|
43
|
+
requestEndpoint: string;
|
|
44
|
+
requestBody: string;
|
|
43
45
|
endpoint: string | undefined;
|
|
44
|
-
response?:
|
|
46
|
+
response?: FetcherResponse;
|
|
45
47
|
startedAt: Date;
|
|
46
48
|
endedAt: Date;
|
|
47
49
|
tags?: string[];
|
|
48
|
-
fetcher:
|
|
50
|
+
fetcher: Fetcher;
|
|
49
51
|
}) {
|
|
50
52
|
// don't send report if the endpoint url is not configured
|
|
51
53
|
if (!endpoint) {
|
|
@@ -85,8 +87,8 @@ export async function submitOutOfBandReportIfConfigured({
|
|
|
85
87
|
message: error.message,
|
|
86
88
|
},
|
|
87
89
|
request: {
|
|
88
|
-
url:
|
|
89
|
-
body:
|
|
90
|
+
url: requestEndpoint,
|
|
91
|
+
body: requestBody,
|
|
90
92
|
},
|
|
91
93
|
response: response
|
|
92
94
|
? {
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
fetch,
|
|
3
|
-
Request,
|
|
4
|
-
Response,
|
|
5
|
-
Body,
|
|
6
|
-
BodyInit,
|
|
7
|
-
Headers,
|
|
8
|
-
HeadersInit,
|
|
9
|
-
URL,
|
|
10
|
-
URLSearchParams,
|
|
11
|
-
} from 'apollo-server-env';
|
|
12
|
-
interface FetchMock extends jest.MockedFunction<typeof fetch> {
|
|
13
|
-
mockResponseOnce(data?: any, headers?: HeadersInit, status?: number): this;
|
|
14
|
-
mockJSONResponseOnce(data?: object, headers?: HeadersInit): this;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const mockFetch = jest.fn(fetch) as unknown as FetchMock;
|
|
18
|
-
|
|
19
|
-
mockFetch.mockResponseOnce = (
|
|
20
|
-
data?: BodyInit,
|
|
21
|
-
headers?: Headers,
|
|
22
|
-
status: number = 200,
|
|
23
|
-
) => {
|
|
24
|
-
return mockFetch.mockImplementationOnce(async () => {
|
|
25
|
-
return new Response(data, {
|
|
26
|
-
status,
|
|
27
|
-
headers,
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
mockFetch.mockJSONResponseOnce = (
|
|
33
|
-
data = {},
|
|
34
|
-
headers?: Headers,
|
|
35
|
-
status?: number,
|
|
36
|
-
) => {
|
|
37
|
-
return mockFetch.mockResponseOnce(
|
|
38
|
-
JSON.stringify(data),
|
|
39
|
-
Object.assign({ 'Content-Type': 'application/json' }, headers),
|
|
40
|
-
status,
|
|
41
|
-
);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const env = {
|
|
45
|
-
fetch: mockFetch,
|
|
46
|
-
Request,
|
|
47
|
-
Response,
|
|
48
|
-
Body,
|
|
49
|
-
Headers,
|
|
50
|
-
URL,
|
|
51
|
-
URLSearchParams,
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
jest.doMock('apollo-server-env', () => env);
|
|
55
|
-
|
|
56
|
-
export = env;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/// <reference path="../make-fetch-happen.d.ts" />
|
|
2
|
-
// This explicit reference shouldn't be needed because the project references
|
|
3
|
-
// the main project, which includes these type declarations. For some reason,
|
|
4
|
-
// VS Code doesn't pick that up though.
|
|
5
|
-
// (This may be related to https://github.com/microsoft/TypeScript/issues/36708.)
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
fetch,
|
|
9
|
-
Response,
|
|
10
|
-
BodyInit,
|
|
11
|
-
Headers,
|
|
12
|
-
HeadersInit
|
|
13
|
-
} from 'apollo-server-env';
|
|
14
|
-
|
|
15
|
-
import fetcher from 'make-fetch-happen';
|
|
16
|
-
|
|
17
|
-
interface MakeFetchHappenMock extends jest.MockedFunction<typeof fetch> {
|
|
18
|
-
mockResponseOnce(data?: any, headers?: HeadersInit, status?: number): this;
|
|
19
|
-
mockJSONResponseOnce(data?: object, headers?: HeadersInit): this;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const mockMakeFetchHappen = jest.fn(fetcher) as unknown as MakeFetchHappenMock;
|
|
23
|
-
const defaults = () => mockMakeFetchHappen;
|
|
24
|
-
|
|
25
|
-
mockMakeFetchHappen.mockResponseOnce = (
|
|
26
|
-
data?: BodyInit,
|
|
27
|
-
headers?: Headers,
|
|
28
|
-
status: number = 200,
|
|
29
|
-
) => {
|
|
30
|
-
return mockMakeFetchHappen.mockImplementationOnce(async () => {
|
|
31
|
-
return new Response(data, {
|
|
32
|
-
status,
|
|
33
|
-
headers,
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
mockMakeFetchHappen.mockJSONResponseOnce = (
|
|
39
|
-
data = {},
|
|
40
|
-
headers?: Headers,
|
|
41
|
-
status?: number,
|
|
42
|
-
) => {
|
|
43
|
-
return mockMakeFetchHappen.mockResponseOnce(
|
|
44
|
-
JSON.stringify(data),
|
|
45
|
-
Object.assign({ 'Content-Type': 'application/json' }, headers),
|
|
46
|
-
status,
|
|
47
|
-
);
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const makeFetchMock = {
|
|
51
|
-
fetch: mockMakeFetchHappen,
|
|
52
|
-
defaults,
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
jest.doMock('make-fetch-happen', () => makeFetchMock);
|
|
56
|
-
|
|
57
|
-
export = makeFetchMock;
|