@apollo/gateway 2.0.0-alpha.2 → 2.0.0-alpha.3
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 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/datasources/RemoteGraphQLDataSource.d.ts.map +1 -1
- package/dist/datasources/RemoteGraphQLDataSource.js +4 -1
- package/dist/datasources/RemoteGraphQLDataSource.js.map +1 -1
- package/dist/executeQueryPlan.d.ts.map +1 -1
- package/dist/executeQueryPlan.js +1 -1
- package/dist/executeQueryPlan.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -6
- package/dist/index.js.map +1 -1
- package/dist/loadSupergraphSdlFromStorage.d.ts +13 -5
- package/dist/loadSupergraphSdlFromStorage.d.ts.map +1 -1
- package/dist/loadSupergraphSdlFromStorage.js +34 -7
- package/dist/loadSupergraphSdlFromStorage.js.map +1 -1
- package/dist/outOfBandReporter.d.ts +10 -12
- package/dist/outOfBandReporter.d.ts.map +1 -1
- package/dist/outOfBandReporter.js +70 -73
- package/dist/outOfBandReporter.js.map +1 -1
- package/package.json +4 -4
- package/src/__mocks__/make-fetch-happen-fetcher.ts +3 -1
- package/src/__tests__/executeQueryPlan.test.ts +598 -0
- package/src/__tests__/gateway/buildService.test.ts +1 -1
- package/src/__tests__/gateway/composedSdl.test.ts +1 -1
- package/src/__tests__/gateway/executor.test.ts +1 -1
- package/src/__tests__/gateway/reporting.test.ts +8 -5
- package/src/__tests__/integration/configuration.test.ts +44 -4
- package/src/__tests__/integration/networkRequests.test.ts +21 -19
- package/src/__tests__/integration/nockMocks.ts +12 -6
- package/src/__tests__/loadSupergraphSdlFromStorage.test.ts +101 -452
- package/src/__tests__/nockAssertions.ts +20 -0
- package/src/config.ts +3 -1
- package/src/datasources/RemoteGraphQLDataSource.ts +8 -2
- package/src/datasources/__tests__/RemoteGraphQLDataSource.test.ts +4 -4
- package/src/executeQueryPlan.ts +11 -1
- package/src/index.ts +26 -12
- package/src/loadSupergraphSdlFromStorage.ts +54 -8
- package/src/outOfBandReporter.ts +87 -89
|
@@ -1,430 +1,96 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
loadSupergraphSdlFromStorage,
|
|
3
|
+
loadSupergraphSdlFromUplinks
|
|
4
|
+
} from '../loadSupergraphSdlFromStorage';
|
|
2
5
|
import { getDefaultFetcher } from '../..';
|
|
3
6
|
import {
|
|
4
7
|
graphRef,
|
|
5
8
|
apiKey,
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
mockCloudConfigUrl1,
|
|
10
|
+
mockCloudConfigUrl2,
|
|
8
11
|
mockOutOfBandReporterUrl,
|
|
12
|
+
mockSupergraphSdlRequest,
|
|
9
13
|
mockOutOfBandReportRequestSuccess,
|
|
10
14
|
mockSupergraphSdlRequestSuccess,
|
|
11
15
|
mockSupergraphSdlRequestIfAfterUnchanged,
|
|
16
|
+
mockSupergraphSdlRequestIfAfter
|
|
12
17
|
} from './integration/nockMocks';
|
|
13
|
-
import
|
|
18
|
+
import { getTestingSupergraphSdl } from "./execution-utils";
|
|
19
|
+
import { nockAfterEach, nockBeforeEach } from './nockAssertions';
|
|
14
20
|
|
|
15
21
|
describe('loadSupergraphSdlFromStorage', () => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
afterAll(async () => {
|
|
19
|
-
if (cleanUp) {
|
|
20
|
-
cleanUp();
|
|
21
|
-
cleanUp = null;
|
|
22
|
-
}
|
|
23
|
-
});
|
|
22
|
+
beforeEach(nockBeforeEach);
|
|
23
|
+
afterEach(nockAfterEach);
|
|
24
24
|
|
|
25
25
|
it('fetches Supergraph SDL as expected', async () => {
|
|
26
26
|
mockSupergraphSdlRequestSuccess();
|
|
27
|
-
|
|
28
27
|
const fetcher = getDefaultFetcher();
|
|
29
28
|
const result = await loadSupergraphSdlFromStorage({
|
|
30
29
|
graphRef,
|
|
31
30
|
apiKey,
|
|
32
|
-
endpoint:
|
|
31
|
+
endpoint: mockCloudConfigUrl1,
|
|
32
|
+
errorReportingEndpoint: undefined,
|
|
33
33
|
fetcher,
|
|
34
34
|
compositionId: null,
|
|
35
|
+
});
|
|
36
|
+
expect(result).toMatchObject({
|
|
37
|
+
id: 'originalId-1234',
|
|
38
|
+
supergraphSdl: getTestingSupergraphSdl(),
|
|
39
|
+
});
|
|
40
|
+
});
|
|
35
41
|
|
|
42
|
+
it('Queries alternate Uplink URL if first one fails', async () => {
|
|
43
|
+
mockSupergraphSdlRequest('originalId-1234', mockCloudConfigUrl1).reply(500);
|
|
44
|
+
mockSupergraphSdlRequestIfAfter('originalId-1234', mockCloudConfigUrl2).reply(
|
|
45
|
+
200,
|
|
46
|
+
JSON.stringify({
|
|
47
|
+
data: {
|
|
48
|
+
routerConfig: {
|
|
49
|
+
__typename: 'RouterConfigResult',
|
|
50
|
+
id: 'originalId-1234',
|
|
51
|
+
supergraphSdl: getTestingSupergraphSdl()
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const fetcher = getDefaultFetcher();
|
|
58
|
+
const result = await loadSupergraphSdlFromUplinks({
|
|
59
|
+
graphRef,
|
|
60
|
+
apiKey,
|
|
61
|
+
endpoints: [mockCloudConfigUrl1, mockCloudConfigUrl2],
|
|
62
|
+
errorReportingEndpoint: undefined,
|
|
63
|
+
fetcher,
|
|
64
|
+
compositionId: "originalId-1234",
|
|
65
|
+
maxRetries: 1
|
|
36
66
|
});
|
|
37
67
|
|
|
38
|
-
expect(result).
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
@core(feature: \\"https://specs.apollo.dev/core/v0.2\\")
|
|
43
|
-
@core(feature: \\"https://specs.apollo.dev/join/v0.2\\", for: EXECUTION)
|
|
44
|
-
@core(feature: \\"https://specs.apollo.dev/tag/v0.1\\")
|
|
45
|
-
{
|
|
46
|
-
query: Query
|
|
47
|
-
mutation: Mutation
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
directive @core(feature: String!, as: String, for: core__Purpose) repeatable on SCHEMA
|
|
51
|
-
|
|
52
|
-
directive @join__field(graph: join__Graph!, requires: join__FieldSet, provides: join__FieldSet, type: String, external: Boolean) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION
|
|
53
|
-
|
|
54
|
-
directive @join__graph(name: String!, url: String!) on ENUM_VALUE
|
|
55
|
-
|
|
56
|
-
directive @join__implements(graph: join__Graph!, interface: String!) repeatable on OBJECT | INTERFACE
|
|
57
|
-
|
|
58
|
-
directive @join__type(graph: join__Graph!, key: join__FieldSet, extension: Boolean! = false) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR
|
|
59
|
-
|
|
60
|
-
directive @stream on FIELD
|
|
61
|
-
|
|
62
|
-
directive @tag(name: String!) repeatable on FIELD_DEFINITION | OBJECT | INTERFACE | UNION
|
|
63
|
-
|
|
64
|
-
directive @transform(from: String!) on FIELD
|
|
65
|
-
|
|
66
|
-
union AccountType
|
|
67
|
-
@join__type(graph: ACCOUNTS)
|
|
68
|
-
@tag(name: \\"from-accounts\\")
|
|
69
|
-
= PasswordAccount | SMSAccount
|
|
70
|
-
|
|
71
|
-
type Amazon
|
|
72
|
-
@join__type(graph: PRODUCT)
|
|
73
|
-
{
|
|
74
|
-
referrer: String
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
union Body
|
|
78
|
-
@join__type(graph: DOCUMENTS)
|
|
79
|
-
= Image | Text
|
|
80
|
-
|
|
81
|
-
type Book implements Product
|
|
82
|
-
@join__implements(graph: INVENTORY, interface: \\"Product\\")
|
|
83
|
-
@join__implements(graph: PRODUCT, interface: \\"Product\\")
|
|
84
|
-
@join__implements(graph: REVIEWS, interface: \\"Product\\")
|
|
85
|
-
@join__type(graph: BOOKS, key: \\"isbn\\")
|
|
86
|
-
@join__type(graph: INVENTORY, key: \\"isbn\\", extension: true)
|
|
87
|
-
@join__type(graph: PRODUCT, key: \\"isbn\\", extension: true)
|
|
88
|
-
@join__type(graph: REVIEWS, key: \\"isbn\\", extension: true)
|
|
89
|
-
{
|
|
90
|
-
isbn: String!
|
|
91
|
-
title: String @join__field(graph: BOOKS) @join__field(graph: PRODUCT, external: true)
|
|
92
|
-
year: Int @join__field(graph: BOOKS) @join__field(graph: PRODUCT, external: true)
|
|
93
|
-
similarBooks: [Book]! @join__field(graph: BOOKS) @join__field(graph: REVIEWS, external: true)
|
|
94
|
-
metadata: [MetadataOrError] @join__field(graph: BOOKS)
|
|
95
|
-
inStock: Boolean @join__field(graph: INVENTORY)
|
|
96
|
-
isCheckedOut: Boolean @join__field(graph: INVENTORY)
|
|
97
|
-
upc: String! @join__field(graph: PRODUCT)
|
|
98
|
-
sku: String! @join__field(graph: PRODUCT)
|
|
99
|
-
name(delimeter: String = \\" \\"): String @join__field(graph: PRODUCT, requires: \\"title year\\")
|
|
100
|
-
price: String @join__field(graph: PRODUCT)
|
|
101
|
-
details: ProductDetailsBook @join__field(graph: PRODUCT)
|
|
102
|
-
reviews: [Review] @join__field(graph: REVIEWS)
|
|
103
|
-
relatedReviews: [Review!]! @join__field(graph: REVIEWS, requires: \\"similarBooks { isbn }\\")
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
union Brand
|
|
107
|
-
@join__type(graph: PRODUCT)
|
|
108
|
-
= Ikea | Amazon
|
|
109
|
-
|
|
110
|
-
enum CacheControlScope
|
|
111
|
-
@join__type(graph: ACCOUNTS)
|
|
112
|
-
@join__type(graph: BOOKS)
|
|
113
|
-
@join__type(graph: PRODUCT)
|
|
114
|
-
{
|
|
115
|
-
PUBLIC
|
|
116
|
-
PRIVATE
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
type Car implements Vehicle
|
|
120
|
-
@join__implements(graph: PRODUCT, interface: \\"Vehicle\\")
|
|
121
|
-
@join__implements(graph: REVIEWS, interface: \\"Vehicle\\")
|
|
122
|
-
@join__type(graph: PRODUCT, key: \\"id\\")
|
|
123
|
-
@join__type(graph: REVIEWS, key: \\"id\\", extension: true)
|
|
124
|
-
{
|
|
125
|
-
id: String!
|
|
126
|
-
description: String @join__field(graph: PRODUCT)
|
|
127
|
-
price: String @join__field(graph: PRODUCT) @join__field(graph: REVIEWS, external: true)
|
|
128
|
-
retailPrice: String @join__field(graph: REVIEWS, requires: \\"price\\")
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
enum core__Purpose {
|
|
132
|
-
\\"\\"\\"
|
|
133
|
-
\`SECURITY\` features provide metadata necessary to securely resolve fields.
|
|
134
|
-
\\"\\"\\"
|
|
135
|
-
SECURITY
|
|
136
|
-
|
|
137
|
-
\\"\\"\\"
|
|
138
|
-
\`EXECUTION\` features provide metadata necessary for operation execution.
|
|
139
|
-
\\"\\"\\"
|
|
140
|
-
EXECUTION
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
type Error
|
|
144
|
-
@join__type(graph: BOOKS)
|
|
145
|
-
@join__type(graph: PRODUCT)
|
|
146
|
-
@join__type(graph: REVIEWS)
|
|
147
|
-
{
|
|
148
|
-
code: Int
|
|
149
|
-
message: String
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
type Furniture implements Product
|
|
153
|
-
@join__implements(graph: INVENTORY, interface: \\"Product\\")
|
|
154
|
-
@join__implements(graph: PRODUCT, interface: \\"Product\\")
|
|
155
|
-
@join__implements(graph: REVIEWS, interface: \\"Product\\")
|
|
156
|
-
@join__type(graph: INVENTORY, key: \\"sku\\", extension: true)
|
|
157
|
-
@join__type(graph: PRODUCT, key: \\"upc\\")
|
|
158
|
-
@join__type(graph: PRODUCT, key: \\"sku\\")
|
|
159
|
-
@join__type(graph: REVIEWS, key: \\"upc\\", extension: true)
|
|
160
|
-
{
|
|
161
|
-
sku: String! @join__field(graph: INVENTORY) @join__field(graph: PRODUCT)
|
|
162
|
-
inStock: Boolean @join__field(graph: INVENTORY)
|
|
163
|
-
isHeavy: Boolean @join__field(graph: INVENTORY)
|
|
164
|
-
upc: String! @join__field(graph: PRODUCT) @join__field(graph: REVIEWS)
|
|
165
|
-
name: String @join__field(graph: PRODUCT)
|
|
166
|
-
price: String @join__field(graph: PRODUCT)
|
|
167
|
-
brand: Brand @join__field(graph: PRODUCT)
|
|
168
|
-
metadata: [MetadataOrError] @join__field(graph: PRODUCT)
|
|
169
|
-
details: ProductDetailsFurniture @join__field(graph: PRODUCT)
|
|
170
|
-
reviews: [Review] @join__field(graph: REVIEWS)
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
type Ikea
|
|
174
|
-
@join__type(graph: PRODUCT)
|
|
175
|
-
{
|
|
176
|
-
asile: Int
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
type Image implements NamedObject
|
|
180
|
-
@join__implements(graph: DOCUMENTS, interface: \\"NamedObject\\")
|
|
181
|
-
@join__type(graph: DOCUMENTS)
|
|
182
|
-
{
|
|
183
|
-
name: String!
|
|
184
|
-
attributes: ImageAttributes!
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
type ImageAttributes
|
|
188
|
-
@join__type(graph: DOCUMENTS)
|
|
189
|
-
{
|
|
190
|
-
url: String!
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
scalar join__FieldSet
|
|
194
|
-
|
|
195
|
-
enum join__Graph {
|
|
196
|
-
ACCOUNTS @join__graph(name: \\"accounts\\", url: \\"https://accounts.api.com.invalid\\")
|
|
197
|
-
BOOKS @join__graph(name: \\"books\\", url: \\"https://books.api.com.invalid\\")
|
|
198
|
-
DOCUMENTS @join__graph(name: \\"documents\\", url: \\"https://documents.api.com.invalid\\")
|
|
199
|
-
INVENTORY @join__graph(name: \\"inventory\\", url: \\"https://inventory.api.com.invalid\\")
|
|
200
|
-
PRODUCT @join__graph(name: \\"product\\", url: \\"https://product.api.com.invalid\\")
|
|
201
|
-
REVIEWS @join__graph(name: \\"reviews\\", url: \\"https://reviews.api.com.invalid\\")
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
scalar JSON
|
|
205
|
-
@join__type(graph: ACCOUNTS)
|
|
206
|
-
@specifiedBy(url: \\"https://json-spec.dev\\")
|
|
207
|
-
|
|
208
|
-
type KeyValue
|
|
209
|
-
@join__type(graph: BOOKS)
|
|
210
|
-
@join__type(graph: PRODUCT)
|
|
211
|
-
@join__type(graph: REVIEWS)
|
|
212
|
-
{
|
|
213
|
-
key: String!
|
|
214
|
-
value: String!
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
type Library
|
|
218
|
-
@join__type(graph: ACCOUNTS, key: \\"id\\", extension: true)
|
|
219
|
-
@join__type(graph: BOOKS, key: \\"id\\")
|
|
220
|
-
{
|
|
221
|
-
id: ID!
|
|
222
|
-
name: String @join__field(graph: ACCOUNTS, external: true) @join__field(graph: BOOKS)
|
|
223
|
-
userAccount(id: ID! = 1): User @join__field(graph: ACCOUNTS, requires: \\"name\\")
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
union MetadataOrError
|
|
227
|
-
@join__type(graph: BOOKS)
|
|
228
|
-
@join__type(graph: PRODUCT)
|
|
229
|
-
@join__type(graph: REVIEWS)
|
|
230
|
-
= KeyValue | Error
|
|
231
|
-
|
|
232
|
-
type Mutation
|
|
233
|
-
@join__type(graph: ACCOUNTS)
|
|
234
|
-
@join__type(graph: REVIEWS)
|
|
235
|
-
{
|
|
236
|
-
login(username: String!, password: String!, userId: String @deprecated(reason: \\"Use username instead\\")): User @join__field(graph: ACCOUNTS)
|
|
237
|
-
reviewProduct(input: ReviewProduct!): Product @join__field(graph: REVIEWS)
|
|
238
|
-
updateReview(review: UpdateReviewInput!): Review @join__field(graph: REVIEWS)
|
|
239
|
-
deleteReview(id: ID!): Boolean @join__field(graph: REVIEWS)
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
type Name
|
|
243
|
-
@join__type(graph: ACCOUNTS)
|
|
244
|
-
{
|
|
245
|
-
first: String
|
|
246
|
-
last: String
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
interface NamedObject
|
|
250
|
-
@join__type(graph: DOCUMENTS)
|
|
251
|
-
{
|
|
252
|
-
name: String!
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
type PasswordAccount
|
|
256
|
-
@join__type(graph: ACCOUNTS, key: \\"email\\")
|
|
257
|
-
{
|
|
258
|
-
email: String!
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
interface Product
|
|
262
|
-
@join__type(graph: INVENTORY)
|
|
263
|
-
@join__type(graph: PRODUCT)
|
|
264
|
-
@join__type(graph: REVIEWS)
|
|
265
|
-
@tag(name: \\"from-reviews\\")
|
|
266
|
-
{
|
|
267
|
-
inStock: Boolean @join__field(graph: INVENTORY)
|
|
268
|
-
upc: String! @join__field(graph: PRODUCT)
|
|
269
|
-
sku: String! @join__field(graph: PRODUCT)
|
|
270
|
-
name: String @join__field(graph: PRODUCT)
|
|
271
|
-
price: String @join__field(graph: PRODUCT)
|
|
272
|
-
details: ProductDetails @join__field(graph: PRODUCT)
|
|
273
|
-
reviews: [Review] @join__field(graph: REVIEWS)
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
interface ProductDetails
|
|
277
|
-
@join__type(graph: PRODUCT)
|
|
278
|
-
{
|
|
279
|
-
country: String
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
type ProductDetailsBook implements ProductDetails
|
|
283
|
-
@join__implements(graph: PRODUCT, interface: \\"ProductDetails\\")
|
|
284
|
-
@join__type(graph: PRODUCT)
|
|
285
|
-
{
|
|
286
|
-
country: String
|
|
287
|
-
pages: Int
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
type ProductDetailsFurniture implements ProductDetails
|
|
291
|
-
@join__implements(graph: PRODUCT, interface: \\"ProductDetails\\")
|
|
292
|
-
@join__type(graph: PRODUCT)
|
|
293
|
-
{
|
|
294
|
-
country: String
|
|
295
|
-
color: String
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
type Query
|
|
299
|
-
@join__type(graph: ACCOUNTS)
|
|
300
|
-
@join__type(graph: BOOKS)
|
|
301
|
-
@join__type(graph: DOCUMENTS)
|
|
302
|
-
@join__type(graph: INVENTORY)
|
|
303
|
-
@join__type(graph: PRODUCT)
|
|
304
|
-
@join__type(graph: REVIEWS)
|
|
305
|
-
{
|
|
306
|
-
user(id: ID!): User @join__field(graph: ACCOUNTS)
|
|
307
|
-
me: User @join__field(graph: ACCOUNTS)
|
|
308
|
-
book(isbn: String!): Book @join__field(graph: BOOKS)
|
|
309
|
-
books: [Book] @join__field(graph: BOOKS)
|
|
310
|
-
library(id: ID!): Library @join__field(graph: BOOKS)
|
|
311
|
-
body: Body! @join__field(graph: DOCUMENTS)
|
|
312
|
-
product(upc: String!): Product @join__field(graph: PRODUCT)
|
|
313
|
-
vehicle(id: String!): Vehicle @join__field(graph: PRODUCT)
|
|
314
|
-
topProducts(first: Int = 5): [Product] @join__field(graph: PRODUCT)
|
|
315
|
-
topCars(first: Int = 5): [Car] @join__field(graph: PRODUCT)
|
|
316
|
-
topReviews(first: Int = 5): [Review] @join__field(graph: REVIEWS)
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
type Review
|
|
320
|
-
@join__type(graph: REVIEWS, key: \\"id\\")
|
|
321
|
-
{
|
|
322
|
-
id: ID!
|
|
323
|
-
body(format: Boolean = false): String
|
|
324
|
-
author: User @join__field(graph: REVIEWS, provides: \\"username\\")
|
|
325
|
-
product: Product
|
|
326
|
-
metadata: [MetadataOrError]
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
input ReviewProduct
|
|
330
|
-
@join__type(graph: REVIEWS)
|
|
331
|
-
{
|
|
332
|
-
upc: String!
|
|
333
|
-
body: String!
|
|
334
|
-
stars: Int @deprecated(reason: \\"Stars are no longer in use\\")
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
type SMSAccount
|
|
338
|
-
@join__type(graph: ACCOUNTS, key: \\"number\\")
|
|
339
|
-
{
|
|
340
|
-
number: String
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
type Text implements NamedObject
|
|
344
|
-
@join__implements(graph: DOCUMENTS, interface: \\"NamedObject\\")
|
|
345
|
-
@join__type(graph: DOCUMENTS)
|
|
346
|
-
{
|
|
347
|
-
name: String!
|
|
348
|
-
attributes: TextAttributes!
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
type TextAttributes
|
|
352
|
-
@join__type(graph: DOCUMENTS)
|
|
353
|
-
{
|
|
354
|
-
bold: Boolean
|
|
355
|
-
text: String
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
union Thing
|
|
359
|
-
@join__type(graph: PRODUCT)
|
|
360
|
-
= Car | Ikea
|
|
361
|
-
|
|
362
|
-
input UpdateReviewInput
|
|
363
|
-
@join__type(graph: REVIEWS)
|
|
364
|
-
{
|
|
365
|
-
id: ID!
|
|
366
|
-
body: String
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
type User
|
|
370
|
-
@join__type(graph: ACCOUNTS, key: \\"id\\")
|
|
371
|
-
@join__type(graph: ACCOUNTS, key: \\"username name { first last }\\")
|
|
372
|
-
@join__type(graph: INVENTORY, key: \\"id\\", extension: true)
|
|
373
|
-
@join__type(graph: PRODUCT, key: \\"id\\", extension: true)
|
|
374
|
-
@join__type(graph: REVIEWS, key: \\"id\\", extension: true)
|
|
375
|
-
@tag(name: \\"from-accounts\\")
|
|
376
|
-
@tag(name: \\"from-reviews\\")
|
|
377
|
-
{
|
|
378
|
-
id: ID! @tag(name: \\"accounts\\")
|
|
379
|
-
name: Name @join__field(graph: ACCOUNTS)
|
|
380
|
-
username: String @join__field(graph: ACCOUNTS) @join__field(graph: REVIEWS, external: true)
|
|
381
|
-
birthDate(locale: String): String @tag(name: \\"admin\\") @tag(name: \\"dev\\") @join__field(graph: ACCOUNTS)
|
|
382
|
-
account: AccountType @join__field(graph: ACCOUNTS)
|
|
383
|
-
metadata: [UserMetadata] @join__field(graph: ACCOUNTS) @join__field(graph: INVENTORY, external: true) @join__field(graph: REVIEWS, external: true)
|
|
384
|
-
ssn: String @join__field(graph: ACCOUNTS)
|
|
385
|
-
goodDescription: Boolean @join__field(graph: INVENTORY, requires: \\"metadata { description }\\")
|
|
386
|
-
vehicle: Vehicle @join__field(graph: PRODUCT)
|
|
387
|
-
thing: Thing @join__field(graph: PRODUCT)
|
|
388
|
-
reviews: [Review] @join__field(graph: REVIEWS)
|
|
389
|
-
numberOfReviews: Int! @join__field(graph: REVIEWS)
|
|
390
|
-
goodAddress: Boolean @join__field(graph: REVIEWS, requires: \\"metadata { address }\\")
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
type UserMetadata
|
|
394
|
-
@join__type(graph: ACCOUNTS)
|
|
395
|
-
@join__type(graph: INVENTORY)
|
|
396
|
-
@join__type(graph: REVIEWS)
|
|
397
|
-
{
|
|
398
|
-
name: String @join__field(graph: ACCOUNTS)
|
|
399
|
-
address: String @join__field(graph: ACCOUNTS) @join__field(graph: REVIEWS, external: true)
|
|
400
|
-
description: String @join__field(graph: ACCOUNTS) @join__field(graph: INVENTORY, external: true)
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
type Van implements Vehicle
|
|
404
|
-
@join__implements(graph: PRODUCT, interface: \\"Vehicle\\")
|
|
405
|
-
@join__implements(graph: REVIEWS, interface: \\"Vehicle\\")
|
|
406
|
-
@join__type(graph: PRODUCT, key: \\"id\\")
|
|
407
|
-
@join__type(graph: REVIEWS, key: \\"id\\", extension: true)
|
|
408
|
-
{
|
|
409
|
-
id: String!
|
|
410
|
-
description: String @join__field(graph: PRODUCT)
|
|
411
|
-
price: String @join__field(graph: PRODUCT) @join__field(graph: REVIEWS, external: true)
|
|
412
|
-
retailPrice: String @join__field(graph: REVIEWS, requires: \\"price\\")
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
interface Vehicle
|
|
416
|
-
@join__type(graph: PRODUCT)
|
|
417
|
-
@join__type(graph: REVIEWS)
|
|
418
|
-
{
|
|
419
|
-
id: String! @join__field(graph: PRODUCT)
|
|
420
|
-
description: String @join__field(graph: PRODUCT)
|
|
421
|
-
price: String @join__field(graph: PRODUCT)
|
|
422
|
-
retailPrice: String @join__field(graph: REVIEWS)
|
|
423
|
-
}",
|
|
424
|
-
}
|
|
425
|
-
`);
|
|
68
|
+
expect(result).toMatchObject({
|
|
69
|
+
id: 'originalId-1234',
|
|
70
|
+
supergraphSdl: getTestingSupergraphSdl(),
|
|
71
|
+
});
|
|
426
72
|
});
|
|
427
73
|
|
|
74
|
+
it('Throws error if all Uplink URLs fail', async () => {
|
|
75
|
+
mockSupergraphSdlRequest("originalId-1234", mockCloudConfigUrl1).reply(500);
|
|
76
|
+
mockSupergraphSdlRequestIfAfter("originalId-1234", mockCloudConfigUrl2).reply(500);
|
|
77
|
+
|
|
78
|
+
const fetcher = getDefaultFetcher();
|
|
79
|
+
await expect(
|
|
80
|
+
loadSupergraphSdlFromUplinks({
|
|
81
|
+
graphRef,
|
|
82
|
+
apiKey,
|
|
83
|
+
endpoints: [mockCloudConfigUrl1, mockCloudConfigUrl2],
|
|
84
|
+
errorReportingEndpoint: undefined,
|
|
85
|
+
fetcher,
|
|
86
|
+
compositionId: "originalId-1234",
|
|
87
|
+
maxRetries: 1
|
|
88
|
+
}),
|
|
89
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
90
|
+
`"An error occurred while fetching your schema from Apollo: 500 Internal Server Error"`,
|
|
91
|
+
);
|
|
92
|
+
})
|
|
93
|
+
|
|
428
94
|
describe('errors', () => {
|
|
429
95
|
it('throws on a malformed response', async () => {
|
|
430
96
|
mockSupergraphSdlRequest().reply(200, 'Invalid JSON');
|
|
@@ -434,13 +100,13 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
434
100
|
loadSupergraphSdlFromStorage({
|
|
435
101
|
graphRef,
|
|
436
102
|
apiKey,
|
|
437
|
-
endpoint:
|
|
103
|
+
endpoint: mockCloudConfigUrl1,
|
|
104
|
+
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
438
105
|
fetcher,
|
|
439
106
|
compositionId: null,
|
|
440
|
-
|
|
441
107
|
}),
|
|
442
108
|
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
443
|
-
`"An error occurred while fetching your schema from Apollo: 200 invalid json response body at https://
|
|
109
|
+
`"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"`,
|
|
444
110
|
);
|
|
445
111
|
});
|
|
446
112
|
|
|
@@ -458,7 +124,8 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
458
124
|
loadSupergraphSdlFromStorage({
|
|
459
125
|
graphRef,
|
|
460
126
|
apiKey,
|
|
461
|
-
endpoint:
|
|
127
|
+
endpoint: mockCloudConfigUrl1,
|
|
128
|
+
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
462
129
|
fetcher,
|
|
463
130
|
compositionId: null,
|
|
464
131
|
}),
|
|
@@ -467,13 +134,15 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
467
134
|
|
|
468
135
|
it("throws on non-OK status codes when `errors` isn't present in a JSON response", async () => {
|
|
469
136
|
mockSupergraphSdlRequest().reply(500);
|
|
137
|
+
mockOutOfBandReportRequestSuccess();
|
|
470
138
|
|
|
471
139
|
const fetcher = getDefaultFetcher();
|
|
472
140
|
await expect(
|
|
473
141
|
loadSupergraphSdlFromStorage({
|
|
474
142
|
graphRef,
|
|
475
143
|
apiKey,
|
|
476
|
-
endpoint:
|
|
144
|
+
endpoint: mockCloudConfigUrl1,
|
|
145
|
+
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
477
146
|
fetcher,
|
|
478
147
|
compositionId: null,
|
|
479
148
|
}),
|
|
@@ -492,42 +161,36 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
492
161
|
loadSupergraphSdlFromStorage({
|
|
493
162
|
graphRef,
|
|
494
163
|
apiKey,
|
|
495
|
-
endpoint:
|
|
164
|
+
endpoint: mockCloudConfigUrl1,
|
|
165
|
+
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
496
166
|
fetcher,
|
|
497
167
|
compositionId: null,
|
|
498
168
|
}),
|
|
499
169
|
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
500
|
-
`"An error occurred while fetching your schema from Apollo: 400 invalid json response body at https://
|
|
170
|
+
`"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"`,
|
|
501
171
|
);
|
|
502
172
|
});
|
|
503
173
|
|
|
504
|
-
it('throws on 400 status response and
|
|
505
|
-
cleanUp = mockedEnv({
|
|
506
|
-
APOLLO_OUT_OF_BAND_REPORTER_ENDPOINT: mockOutOfBandReporterUrl,
|
|
507
|
-
});
|
|
174
|
+
it('throws on 400 status response and does not submit an out of band error', async () => {
|
|
508
175
|
|
|
509
176
|
mockSupergraphSdlRequest().reply(400);
|
|
510
|
-
mockOutOfBandReportRequestSuccess();
|
|
511
177
|
|
|
512
178
|
const fetcher = getDefaultFetcher();
|
|
513
179
|
await expect(
|
|
514
180
|
loadSupergraphSdlFromStorage({
|
|
515
181
|
graphRef,
|
|
516
182
|
apiKey,
|
|
517
|
-
endpoint:
|
|
183
|
+
endpoint: mockCloudConfigUrl1,
|
|
184
|
+
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
518
185
|
fetcher,
|
|
519
186
|
compositionId: null,
|
|
520
187
|
}),
|
|
521
188
|
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
522
|
-
`"An error occurred while fetching your schema from Apollo: 400 invalid json response body at https://
|
|
189
|
+
`"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"`,
|
|
523
190
|
);
|
|
524
191
|
});
|
|
525
192
|
|
|
526
193
|
it('throws on 413 status response and successfully submits an out of band error', async () => {
|
|
527
|
-
cleanUp = mockedEnv({
|
|
528
|
-
APOLLO_OUT_OF_BAND_REPORTER_ENDPOINT: mockOutOfBandReporterUrl,
|
|
529
|
-
});
|
|
530
|
-
|
|
531
194
|
mockSupergraphSdlRequest().reply(413);
|
|
532
195
|
mockOutOfBandReportRequestSuccess();
|
|
533
196
|
|
|
@@ -536,7 +199,8 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
536
199
|
loadSupergraphSdlFromStorage({
|
|
537
200
|
graphRef,
|
|
538
201
|
apiKey,
|
|
539
|
-
endpoint:
|
|
202
|
+
endpoint: mockCloudConfigUrl1,
|
|
203
|
+
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
540
204
|
fetcher,
|
|
541
205
|
compositionId: null,
|
|
542
206
|
}),
|
|
@@ -546,10 +210,6 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
546
210
|
});
|
|
547
211
|
|
|
548
212
|
it('throws on 422 status response and successfully submits an out of band error', async () => {
|
|
549
|
-
cleanUp = mockedEnv({
|
|
550
|
-
APOLLO_OUT_OF_BAND_REPORTER_ENDPOINT: mockOutOfBandReporterUrl,
|
|
551
|
-
});
|
|
552
|
-
|
|
553
213
|
mockSupergraphSdlRequest().reply(422);
|
|
554
214
|
mockOutOfBandReportRequestSuccess();
|
|
555
215
|
|
|
@@ -558,7 +218,8 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
558
218
|
loadSupergraphSdlFromStorage({
|
|
559
219
|
graphRef,
|
|
560
220
|
apiKey,
|
|
561
|
-
endpoint:
|
|
221
|
+
endpoint: mockCloudConfigUrl1,
|
|
222
|
+
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
562
223
|
fetcher,
|
|
563
224
|
compositionId: null,
|
|
564
225
|
}),
|
|
@@ -568,10 +229,6 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
568
229
|
});
|
|
569
230
|
|
|
570
231
|
it('throws on 408 status response and successfully submits an out of band error', async () => {
|
|
571
|
-
cleanUp = mockedEnv({
|
|
572
|
-
APOLLO_OUT_OF_BAND_REPORTER_ENDPOINT: mockOutOfBandReporterUrl,
|
|
573
|
-
});
|
|
574
|
-
|
|
575
232
|
mockSupergraphSdlRequest().reply(408);
|
|
576
233
|
mockOutOfBandReportRequestSuccess();
|
|
577
234
|
|
|
@@ -580,7 +237,8 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
580
237
|
loadSupergraphSdlFromStorage({
|
|
581
238
|
graphRef,
|
|
582
239
|
apiKey,
|
|
583
|
-
endpoint:
|
|
240
|
+
endpoint: mockCloudConfigUrl1,
|
|
241
|
+
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
584
242
|
fetcher,
|
|
585
243
|
compositionId: null,
|
|
586
244
|
}),
|
|
@@ -591,9 +249,6 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
591
249
|
});
|
|
592
250
|
|
|
593
251
|
it('throws on 504 status response and successfully submits an out of band error', async () => {
|
|
594
|
-
cleanUp = mockedEnv({
|
|
595
|
-
APOLLO_OUT_OF_BAND_REPORTER_ENDPOINT: mockOutOfBandReporterUrl,
|
|
596
|
-
});
|
|
597
252
|
|
|
598
253
|
mockSupergraphSdlRequest().reply(504);
|
|
599
254
|
mockOutOfBandReportRequestSuccess();
|
|
@@ -603,7 +258,8 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
603
258
|
loadSupergraphSdlFromStorage({
|
|
604
259
|
graphRef,
|
|
605
260
|
apiKey,
|
|
606
|
-
endpoint:
|
|
261
|
+
endpoint: mockCloudConfigUrl1,
|
|
262
|
+
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
607
263
|
fetcher,
|
|
608
264
|
compositionId: null,
|
|
609
265
|
}),
|
|
@@ -613,10 +269,6 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
613
269
|
});
|
|
614
270
|
|
|
615
271
|
it('throws when there is no response and successfully submits an out of band error', async () => {
|
|
616
|
-
cleanUp = mockedEnv({
|
|
617
|
-
APOLLO_OUT_OF_BAND_REPORTER_ENDPOINT: mockOutOfBandReporterUrl,
|
|
618
|
-
});
|
|
619
|
-
|
|
620
272
|
mockSupergraphSdlRequest().replyWithError('no response');
|
|
621
273
|
mockOutOfBandReportRequestSuccess();
|
|
622
274
|
|
|
@@ -625,20 +277,17 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
625
277
|
loadSupergraphSdlFromStorage({
|
|
626
278
|
graphRef,
|
|
627
279
|
apiKey,
|
|
628
|
-
endpoint:
|
|
280
|
+
endpoint: mockCloudConfigUrl1,
|
|
281
|
+
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
629
282
|
fetcher,
|
|
630
283
|
compositionId: null,
|
|
631
284
|
}),
|
|
632
285
|
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
633
|
-
`"An error occurred while fetching your schema from Apollo: request to https://
|
|
286
|
+
`"An error occurred while fetching your schema from Apollo: request to https://example1.cloud-config-url.com/cloudconfig/ failed, reason: no response"`,
|
|
634
287
|
);
|
|
635
288
|
});
|
|
636
289
|
|
|
637
290
|
it('throws on 502 status response and successfully submits an out of band error', async () => {
|
|
638
|
-
cleanUp = mockedEnv({
|
|
639
|
-
APOLLO_OUT_OF_BAND_REPORTER_ENDPOINT: mockOutOfBandReporterUrl,
|
|
640
|
-
});
|
|
641
|
-
|
|
642
291
|
mockSupergraphSdlRequest().reply(502);
|
|
643
292
|
mockOutOfBandReportRequestSuccess();
|
|
644
293
|
|
|
@@ -647,7 +296,8 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
647
296
|
loadSupergraphSdlFromStorage({
|
|
648
297
|
graphRef,
|
|
649
298
|
apiKey,
|
|
650
|
-
endpoint:
|
|
299
|
+
endpoint: mockCloudConfigUrl1,
|
|
300
|
+
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
651
301
|
fetcher,
|
|
652
302
|
compositionId: null,
|
|
653
303
|
}),
|
|
@@ -657,10 +307,6 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
657
307
|
});
|
|
658
308
|
|
|
659
309
|
it('throws on 503 status response and successfully submits an out of band error', async () => {
|
|
660
|
-
cleanUp = mockedEnv({
|
|
661
|
-
APOLLO_OUT_OF_BAND_REPORTER_ENDPOINT: mockOutOfBandReporterUrl,
|
|
662
|
-
});
|
|
663
|
-
|
|
664
310
|
mockSupergraphSdlRequest().reply(503);
|
|
665
311
|
mockOutOfBandReportRequestSuccess();
|
|
666
312
|
|
|
@@ -669,7 +315,8 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
669
315
|
loadSupergraphSdlFromStorage({
|
|
670
316
|
graphRef,
|
|
671
317
|
apiKey,
|
|
672
|
-
endpoint:
|
|
318
|
+
endpoint: mockCloudConfigUrl1,
|
|
319
|
+
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
673
320
|
fetcher,
|
|
674
321
|
compositionId: null,
|
|
675
322
|
}),
|
|
@@ -685,10 +332,12 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
685
332
|
const result = await loadSupergraphSdlFromStorage({
|
|
686
333
|
graphRef,
|
|
687
334
|
apiKey,
|
|
688
|
-
endpoint:
|
|
335
|
+
endpoint: mockCloudConfigUrl1,
|
|
336
|
+
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
689
337
|
fetcher,
|
|
690
338
|
compositionId: "id-1234",
|
|
691
339
|
});
|
|
692
340
|
expect(result).toBeNull();
|
|
693
341
|
});
|
|
694
342
|
});
|
|
343
|
+
|