@apollo/gateway 0.43.1 → 2.0.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 (39) hide show
  1. package/CHANGELOG.md +2 -4
  2. package/LICENSE +95 -0
  3. package/dist/executeQueryPlan.d.ts +2 -3
  4. package/dist/executeQueryPlan.d.ts.map +1 -1
  5. package/dist/executeQueryPlan.js +2 -27
  6. package/dist/executeQueryPlan.js.map +1 -1
  7. package/dist/index.d.ts +2 -2
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +22 -41
  10. package/dist/index.js.map +1 -1
  11. package/package.json +7 -5
  12. package/src/__tests__/build-query-plan.feature +34 -24
  13. package/src/__tests__/buildQueryPlan.test.ts +76 -840
  14. package/src/__tests__/executeQueryPlan.test.ts +543 -537
  15. package/src/__tests__/execution-utils.ts +20 -26
  16. package/src/__tests__/gateway/lifecycle-hooks.test.ts +26 -4
  17. package/src/__tests__/gateway/reporting.test.ts +0 -14
  18. package/src/__tests__/integration/abstract-types.test.ts +40 -52
  19. package/src/__tests__/integration/boolean.test.ts +3 -1
  20. package/src/__tests__/integration/complex-key.test.ts +40 -55
  21. package/src/__tests__/integration/configuration.test.ts +5 -5
  22. package/src/__tests__/integration/custom-directives.test.ts +8 -2
  23. package/src/__tests__/integration/multiple-key.test.ts +10 -11
  24. package/src/__tests__/integration/requires.test.ts +2 -2
  25. package/src/__tests__/integration/scope.test.ts +19 -30
  26. package/src/__tests__/integration/value-types.test.ts +31 -31
  27. package/src/__tests__/loadSupergraphSdlFromStorage.test.ts +217 -142
  28. package/src/__tests__/queryPlanCucumber.test.ts +4 -18
  29. package/src/core/__tests__/core.test.ts +1 -0
  30. package/src/executeQueryPlan.ts +1 -32
  31. package/src/index.ts +39 -80
  32. package/src/utilities/__tests__/cleanErrorOfInaccessibleElements.test.ts +4 -4
  33. package/LICENSE.md +0 -21
  34. package/dist/core/index.d.ts +0 -13
  35. package/dist/core/index.d.ts.map +0 -1
  36. package/dist/core/index.js +0 -43
  37. package/dist/core/index.js.map +0 -1
  38. package/src/__tests__/build-query-plan-fragmentization.feature +0 -282
  39. package/src/core/index.ts +0 -51
@@ -36,313 +36,388 @@ describe('loadSupergraphSdlFromStorage', () => {
36
36
  Object {
37
37
  "id": "originalId-1234",
38
38
  "supergraphSdl": "schema
39
- @core(feature: \\"https://specs.apollo.dev/core/v0.2\\"),
40
- @core(feature: \\"https://specs.apollo.dev/join/v0.1\\", for: EXECUTION),
39
+ @core(feature: \\"https://specs.apollo.dev/core/v0.2\\")
40
+ @core(feature: \\"https://specs.apollo.dev/join/v0.2\\", for: EXECUTION)
41
41
  @core(feature: \\"https://specs.apollo.dev/tag/v0.1\\")
42
42
  {
43
43
  query: Query
44
44
  mutation: Mutation
45
45
  }
46
46
 
47
- directive @core(as: String, feature: String!, for: core__Purpose) repeatable on SCHEMA
47
+ directive @core(feature: String!, as: String, for: core__Purpose) repeatable on SCHEMA
48
48
 
49
- directive @join__field(graph: join__Graph, provides: join__FieldSet, requires: join__FieldSet) on FIELD_DEFINITION
49
+ directive @join__field(graph: join__Graph!, requires: join__FieldSet, provides: join__FieldSet, type: String, external: Boolean) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION
50
50
 
51
51
  directive @join__graph(name: String!, url: String!) on ENUM_VALUE
52
52
 
53
- directive @join__owner(graph: join__Graph!) on INTERFACE | OBJECT
53
+ directive @join__implements(graph: join__Graph!, interface: String!) repeatable on OBJECT | INTERFACE
54
54
 
55
- directive @join__type(graph: join__Graph!, key: join__FieldSet) repeatable on INTERFACE | OBJECT
55
+ directive @join__type(graph: join__Graph!, key: join__FieldSet, extension: Boolean! = false) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR
56
56
 
57
57
  directive @stream on FIELD
58
58
 
59
- directive @tag(name: String!) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION
59
+ directive @tag(name: String!) repeatable on FIELD_DEFINITION | OBJECT | INTERFACE | UNION
60
60
 
61
61
  directive @transform(from: String!) on FIELD
62
62
 
63
63
  union AccountType
64
+ @join__type(graph: ACCOUNTS)
64
65
  @tag(name: \\"from-accounts\\")
65
- = PasswordAccount | SMSAccount
66
+ = PasswordAccount | SMSAccount
66
67
 
67
- type Amazon {
68
+ type Amazon
69
+ @join__type(graph: PRODUCT)
70
+ {
68
71
  referrer: String
69
72
  }
70
73
 
71
- union Body = Image | Text
74
+ union Body
75
+ @join__type(graph: DOCUMENTS)
76
+ = Image | Text
72
77
 
73
78
  type Book implements Product
74
- @join__owner(graph: BOOKS)
79
+ @join__implements(graph: INVENTORY, interface: \\"Product\\")
80
+ @join__implements(graph: PRODUCT, interface: \\"Product\\")
81
+ @join__implements(graph: REVIEWS, interface: \\"Product\\")
75
82
  @join__type(graph: BOOKS, key: \\"isbn\\")
76
- @join__type(graph: INVENTORY, key: \\"isbn\\")
77
- @join__type(graph: PRODUCT, key: \\"isbn\\")
78
- @join__type(graph: REVIEWS, key: \\"isbn\\")
83
+ @join__type(graph: INVENTORY, key: \\"isbn\\", extension: true)
84
+ @join__type(graph: PRODUCT, key: \\"isbn\\", extension: true)
85
+ @join__type(graph: REVIEWS, key: \\"isbn\\", extension: true)
79
86
  {
80
- details: ProductDetailsBook @join__field(graph: PRODUCT)
87
+ isbn: String!
88
+ title: String @join__field(graph: BOOKS) @join__field(graph: PRODUCT, external: true)
89
+ year: Int @join__field(graph: BOOKS) @join__field(graph: PRODUCT, external: true)
90
+ similarBooks: [Book]! @join__field(graph: BOOKS) @join__field(graph: REVIEWS, external: true)
91
+ metadata: [MetadataOrError] @join__field(graph: BOOKS)
81
92
  inStock: Boolean @join__field(graph: INVENTORY)
82
93
  isCheckedOut: Boolean @join__field(graph: INVENTORY)
83
- isbn: String! @join__field(graph: BOOKS)
84
- metadata: [MetadataOrError] @join__field(graph: BOOKS)
94
+ upc: String! @join__field(graph: PRODUCT)
95
+ sku: String! @join__field(graph: PRODUCT)
85
96
  name(delimeter: String = \\" \\"): String @join__field(graph: PRODUCT, requires: \\"title year\\")
86
97
  price: String @join__field(graph: PRODUCT)
87
- relatedReviews: [Review!]! @join__field(graph: REVIEWS, requires: \\"similarBooks{isbn}\\")
98
+ details: ProductDetailsBook @join__field(graph: PRODUCT)
88
99
  reviews: [Review] @join__field(graph: REVIEWS)
89
- similarBooks: [Book]! @join__field(graph: BOOKS)
90
- sku: String! @join__field(graph: PRODUCT)
91
- title: String @join__field(graph: BOOKS)
92
- upc: String! @join__field(graph: PRODUCT)
93
- year: Int @join__field(graph: BOOKS)
100
+ relatedReviews: [Review!]! @join__field(graph: REVIEWS, requires: \\"similarBooks { isbn }\\")
94
101
  }
95
102
 
96
- union Brand = Amazon | Ikea
103
+ union Brand
104
+ @join__type(graph: PRODUCT)
105
+ = Ikea | Amazon
97
106
 
98
- enum CacheControlScope {
99
- PRIVATE
107
+ enum CacheControlScope
108
+ @join__type(graph: ACCOUNTS)
109
+ @join__type(graph: BOOKS)
110
+ @join__type(graph: PRODUCT)
111
+ {
100
112
  PUBLIC
113
+ PRIVATE
101
114
  }
102
115
 
103
116
  type Car implements Vehicle
104
- @join__owner(graph: PRODUCT)
117
+ @join__implements(graph: PRODUCT, interface: \\"Vehicle\\")
118
+ @join__implements(graph: REVIEWS, interface: \\"Vehicle\\")
105
119
  @join__type(graph: PRODUCT, key: \\"id\\")
106
- @join__type(graph: REVIEWS, key: \\"id\\")
120
+ @join__type(graph: REVIEWS, key: \\"id\\", extension: true)
107
121
  {
122
+ id: String!
108
123
  description: String @join__field(graph: PRODUCT)
109
- id: String! @join__field(graph: PRODUCT)
110
- price: String @join__field(graph: PRODUCT)
124
+ price: String @join__field(graph: PRODUCT) @join__field(graph: REVIEWS, external: true)
111
125
  retailPrice: String @join__field(graph: REVIEWS, requires: \\"price\\")
112
126
  }
113
127
 
114
- type Error {
128
+ enum core__Purpose {
129
+ \\"\\"\\"
130
+ \`SECURITY\` features provide metadata necessary to securely resolve fields.
131
+ \\"\\"\\"
132
+ SECURITY
133
+
134
+ \\"\\"\\"
135
+ \`EXECUTION\` features provide metadata necessary for operation execution.
136
+ \\"\\"\\"
137
+ EXECUTION
138
+ }
139
+
140
+ type Error
141
+ @join__type(graph: BOOKS)
142
+ @join__type(graph: PRODUCT)
143
+ @join__type(graph: REVIEWS)
144
+ {
115
145
  code: Int
116
146
  message: String
117
147
  }
118
148
 
119
149
  type Furniture implements Product
120
- @join__owner(graph: PRODUCT)
150
+ @join__implements(graph: INVENTORY, interface: \\"Product\\")
151
+ @join__implements(graph: PRODUCT, interface: \\"Product\\")
152
+ @join__implements(graph: REVIEWS, interface: \\"Product\\")
153
+ @join__type(graph: INVENTORY, key: \\"sku\\", extension: true)
121
154
  @join__type(graph: PRODUCT, key: \\"upc\\")
122
155
  @join__type(graph: PRODUCT, key: \\"sku\\")
123
- @join__type(graph: INVENTORY, key: \\"sku\\")
124
- @join__type(graph: REVIEWS, key: \\"upc\\")
156
+ @join__type(graph: REVIEWS, key: \\"upc\\", extension: true)
125
157
  {
126
- brand: Brand @join__field(graph: PRODUCT)
127
- details: ProductDetailsFurniture @join__field(graph: PRODUCT)
158
+ sku: String! @join__field(graph: INVENTORY) @join__field(graph: PRODUCT)
128
159
  inStock: Boolean @join__field(graph: INVENTORY)
129
160
  isHeavy: Boolean @join__field(graph: INVENTORY)
130
- metadata: [MetadataOrError] @join__field(graph: PRODUCT)
161
+ upc: String! @join__field(graph: PRODUCT) @join__field(graph: REVIEWS)
131
162
  name: String @join__field(graph: PRODUCT)
132
163
  price: String @join__field(graph: PRODUCT)
164
+ brand: Brand @join__field(graph: PRODUCT)
165
+ metadata: [MetadataOrError] @join__field(graph: PRODUCT)
166
+ details: ProductDetailsFurniture @join__field(graph: PRODUCT)
133
167
  reviews: [Review] @join__field(graph: REVIEWS)
134
- sku: String! @join__field(graph: PRODUCT)
135
- upc: String! @join__field(graph: PRODUCT)
136
168
  }
137
169
 
138
- type Ikea {
170
+ type Ikea
171
+ @join__type(graph: PRODUCT)
172
+ {
139
173
  asile: Int
140
174
  }
141
175
 
142
- type Image implements NamedObject {
143
- attributes: ImageAttributes!
176
+ type Image implements NamedObject
177
+ @join__implements(graph: DOCUMENTS, interface: \\"NamedObject\\")
178
+ @join__type(graph: DOCUMENTS)
179
+ {
144
180
  name: String!
181
+ attributes: ImageAttributes!
145
182
  }
146
183
 
147
- type ImageAttributes {
184
+ type ImageAttributes
185
+ @join__type(graph: DOCUMENTS)
186
+ {
148
187
  url: String!
149
188
  }
150
189
 
151
- scalar JSON @specifiedBy(url: \\"https://json-spec.dev\\")
190
+ scalar join__FieldSet
152
191
 
153
- type KeyValue {
192
+ enum join__Graph {
193
+ ACCOUNTS @join__graph(name: \\"accounts\\", url: \\"https://accounts.api.com\\")
194
+ BOOKS @join__graph(name: \\"books\\", url: \\"https://books.api.com\\")
195
+ DOCUMENTS @join__graph(name: \\"documents\\", url: \\"https://documents.api.com\\")
196
+ INVENTORY @join__graph(name: \\"inventory\\", url: \\"https://inventory.api.com\\")
197
+ PRODUCT @join__graph(name: \\"product\\", url: \\"https://product.api.com\\")
198
+ REVIEWS @join__graph(name: \\"reviews\\", url: \\"https://reviews.api.com\\")
199
+ }
200
+
201
+ scalar JSON
202
+ @join__type(graph: ACCOUNTS)
203
+ @specifiedBy(url: \\"https://json-spec.dev\\")
204
+
205
+ type KeyValue
206
+ @join__type(graph: BOOKS)
207
+ @join__type(graph: PRODUCT)
208
+ @join__type(graph: REVIEWS)
209
+ {
154
210
  key: String!
155
211
  value: String!
156
212
  }
157
213
 
158
214
  type Library
159
- @join__owner(graph: BOOKS)
215
+ @join__type(graph: ACCOUNTS, key: \\"id\\", extension: true)
160
216
  @join__type(graph: BOOKS, key: \\"id\\")
161
- @join__type(graph: ACCOUNTS, key: \\"id\\")
162
217
  {
163
- id: ID! @join__field(graph: BOOKS)
164
- name: String @join__field(graph: BOOKS)
218
+ id: ID!
219
+ name: String @join__field(graph: ACCOUNTS, external: true) @join__field(graph: BOOKS)
165
220
  userAccount(id: ID! = 1): User @join__field(graph: ACCOUNTS, requires: \\"name\\")
166
221
  }
167
222
 
168
- union MetadataOrError = Error | KeyValue
223
+ union MetadataOrError
224
+ @join__type(graph: BOOKS)
225
+ @join__type(graph: PRODUCT)
226
+ @join__type(graph: REVIEWS)
227
+ = KeyValue | Error
169
228
 
170
- type Mutation {
171
- deleteReview(id: ID!): Boolean @join__field(graph: REVIEWS)
172
- login(password: String!, userId: String @deprecated(reason: \\"Use username instead\\"), username: String!): User @join__field(graph: ACCOUNTS)
229
+ type Mutation
230
+ @join__type(graph: ACCOUNTS)
231
+ @join__type(graph: REVIEWS)
232
+ {
233
+ login(username: String!, password: String!, userId: String @deprecated(reason: \\"Use username instead\\")): User @join__field(graph: ACCOUNTS)
173
234
  reviewProduct(input: ReviewProduct!): Product @join__field(graph: REVIEWS)
174
235
  updateReview(review: UpdateReviewInput!): Review @join__field(graph: REVIEWS)
236
+ deleteReview(id: ID!): Boolean @join__field(graph: REVIEWS)
175
237
  }
176
238
 
177
- type Name {
239
+ type Name
240
+ @join__type(graph: ACCOUNTS)
241
+ {
178
242
  first: String
179
243
  last: String
180
244
  }
181
245
 
182
- interface NamedObject {
246
+ interface NamedObject
247
+ @join__type(graph: DOCUMENTS)
248
+ {
183
249
  name: String!
184
250
  }
185
251
 
186
252
  type PasswordAccount
187
- @join__owner(graph: ACCOUNTS)
188
253
  @join__type(graph: ACCOUNTS, key: \\"email\\")
189
254
  {
190
- email: String! @join__field(graph: ACCOUNTS)
255
+ email: String!
191
256
  }
192
257
 
193
258
  interface Product
259
+ @join__type(graph: INVENTORY)
260
+ @join__type(graph: PRODUCT)
261
+ @join__type(graph: REVIEWS)
194
262
  @tag(name: \\"from-reviews\\")
195
263
  {
196
- details: ProductDetails
197
- inStock: Boolean
198
- name: String
199
- price: String
200
- reviews: [Review]
201
- sku: String!
202
- upc: String!
264
+ inStock: Boolean @join__field(graph: INVENTORY)
265
+ upc: String! @join__field(graph: PRODUCT)
266
+ sku: String! @join__field(graph: PRODUCT)
267
+ name: String @join__field(graph: PRODUCT)
268
+ price: String @join__field(graph: PRODUCT)
269
+ details: ProductDetails @join__field(graph: PRODUCT)
270
+ reviews: [Review] @join__field(graph: REVIEWS)
203
271
  }
204
272
 
205
- interface ProductDetails {
273
+ interface ProductDetails
274
+ @join__type(graph: PRODUCT)
275
+ {
206
276
  country: String
207
277
  }
208
278
 
209
- type ProductDetailsBook implements ProductDetails {
279
+ type ProductDetailsBook implements ProductDetails
280
+ @join__implements(graph: PRODUCT, interface: \\"ProductDetails\\")
281
+ @join__type(graph: PRODUCT)
282
+ {
210
283
  country: String
211
284
  pages: Int
212
285
  }
213
286
 
214
- type ProductDetailsFurniture implements ProductDetails {
215
- color: String
287
+ type ProductDetailsFurniture implements ProductDetails
288
+ @join__implements(graph: PRODUCT, interface: \\"ProductDetails\\")
289
+ @join__type(graph: PRODUCT)
290
+ {
216
291
  country: String
292
+ color: String
217
293
  }
218
294
 
219
- type Query {
220
- body: Body! @join__field(graph: DOCUMENTS)
295
+ type Query
296
+ @join__type(graph: ACCOUNTS)
297
+ @join__type(graph: BOOKS)
298
+ @join__type(graph: DOCUMENTS)
299
+ @join__type(graph: INVENTORY)
300
+ @join__type(graph: PRODUCT)
301
+ @join__type(graph: REVIEWS)
302
+ {
303
+ user(id: ID!): User @join__field(graph: ACCOUNTS)
304
+ me: User @join__field(graph: ACCOUNTS)
221
305
  book(isbn: String!): Book @join__field(graph: BOOKS)
222
306
  books: [Book] @join__field(graph: BOOKS)
223
307
  library(id: ID!): Library @join__field(graph: BOOKS)
224
- me: User @join__field(graph: ACCOUNTS)
308
+ body: Body! @join__field(graph: DOCUMENTS)
225
309
  product(upc: String!): Product @join__field(graph: PRODUCT)
226
- topCars(first: Int = 5): [Car] @join__field(graph: PRODUCT)
310
+ vehicle(id: String!): Vehicle @join__field(graph: PRODUCT)
227
311
  topProducts(first: Int = 5): [Product] @join__field(graph: PRODUCT)
312
+ topCars(first: Int = 5): [Car] @join__field(graph: PRODUCT)
228
313
  topReviews(first: Int = 5): [Review] @join__field(graph: REVIEWS)
229
- user(id: ID!): User @join__field(graph: ACCOUNTS)
230
- vehicle(id: String!): Vehicle @join__field(graph: PRODUCT)
231
314
  }
232
315
 
233
316
  type Review
234
- @join__owner(graph: REVIEWS)
235
317
  @join__type(graph: REVIEWS, key: \\"id\\")
236
318
  {
319
+ id: ID!
320
+ body(format: Boolean = false): String
237
321
  author: User @join__field(graph: REVIEWS, provides: \\"username\\")
238
- body(format: Boolean = false): String @join__field(graph: REVIEWS)
239
- id: ID! @join__field(graph: REVIEWS)
240
- metadata: [MetadataOrError] @join__field(graph: REVIEWS)
241
- product: Product @join__field(graph: REVIEWS)
322
+ product: Product
323
+ metadata: [MetadataOrError]
242
324
  }
243
325
 
244
- input ReviewProduct {
326
+ input ReviewProduct
327
+ @join__type(graph: REVIEWS)
328
+ {
329
+ upc: String!
245
330
  body: String!
246
331
  stars: Int @deprecated(reason: \\"Stars are no longer in use\\")
247
- upc: String!
248
332
  }
249
333
 
250
334
  type SMSAccount
251
- @join__owner(graph: ACCOUNTS)
252
335
  @join__type(graph: ACCOUNTS, key: \\"number\\")
253
336
  {
254
- number: String @join__field(graph: ACCOUNTS)
337
+ number: String
255
338
  }
256
339
 
257
- type Text implements NamedObject {
258
- attributes: TextAttributes!
340
+ type Text implements NamedObject
341
+ @join__implements(graph: DOCUMENTS, interface: \\"NamedObject\\")
342
+ @join__type(graph: DOCUMENTS)
343
+ {
259
344
  name: String!
345
+ attributes: TextAttributes!
260
346
  }
261
347
 
262
- type TextAttributes {
348
+ type TextAttributes
349
+ @join__type(graph: DOCUMENTS)
350
+ {
263
351
  bold: Boolean
264
352
  text: String
265
353
  }
266
354
 
267
- union Thing = Car | Ikea
355
+ union Thing
356
+ @join__type(graph: PRODUCT)
357
+ = Car | Ikea
268
358
 
269
- input UpdateReviewInput {
270
- body: String
359
+ input UpdateReviewInput
360
+ @join__type(graph: REVIEWS)
361
+ {
271
362
  id: ID!
363
+ body: String
272
364
  }
273
365
 
274
366
  type User
275
- @join__owner(graph: ACCOUNTS)
276
367
  @join__type(graph: ACCOUNTS, key: \\"id\\")
277
- @join__type(graph: ACCOUNTS, key: \\"username name{first last}\\")
278
- @join__type(graph: INVENTORY, key: \\"id\\")
279
- @join__type(graph: PRODUCT, key: \\"id\\")
280
- @join__type(graph: REVIEWS, key: \\"id\\")
368
+ @join__type(graph: ACCOUNTS, key: \\"username name { first last }\\")
369
+ @join__type(graph: INVENTORY, key: \\"id\\", extension: true)
370
+ @join__type(graph: PRODUCT, key: \\"id\\", extension: true)
371
+ @join__type(graph: REVIEWS, key: \\"id\\", extension: true)
281
372
  @tag(name: \\"from-accounts\\")
282
373
  @tag(name: \\"from-reviews\\")
283
374
  {
284
- account: AccountType @join__field(graph: ACCOUNTS)
285
- birthDate(locale: String): String @join__field(graph: ACCOUNTS) @tag(name: \\"admin\\") @tag(name: \\"dev\\")
286
- goodAddress: Boolean @join__field(graph: REVIEWS, requires: \\"metadata{address}\\")
287
- goodDescription: Boolean @join__field(graph: INVENTORY, requires: \\"metadata{description}\\")
288
- id: ID! @join__field(graph: ACCOUNTS) @tag(name: \\"accounts\\") @tag(name: \\"on-external\\")
289
- metadata: [UserMetadata] @join__field(graph: ACCOUNTS)
375
+ id: ID! @tag(name: \\"accounts\\")
290
376
  name: Name @join__field(graph: ACCOUNTS)
291
- numberOfReviews: Int! @join__field(graph: REVIEWS)
292
- reviews: [Review] @join__field(graph: REVIEWS)
377
+ username: String @join__field(graph: ACCOUNTS) @join__field(graph: REVIEWS, external: true)
378
+ birthDate(locale: String): String @tag(name: \\"admin\\") @tag(name: \\"dev\\") @join__field(graph: ACCOUNTS)
379
+ account: AccountType @join__field(graph: ACCOUNTS)
380
+ metadata: [UserMetadata] @join__field(graph: ACCOUNTS) @join__field(graph: INVENTORY, external: true) @join__field(graph: REVIEWS, external: true)
293
381
  ssn: String @join__field(graph: ACCOUNTS)
294
- thing: Thing @join__field(graph: PRODUCT)
295
- username: String @join__field(graph: ACCOUNTS)
382
+ goodDescription: Boolean @join__field(graph: INVENTORY, requires: \\"metadata { description }\\")
296
383
  vehicle: Vehicle @join__field(graph: PRODUCT)
384
+ thing: Thing @join__field(graph: PRODUCT)
385
+ reviews: [Review] @join__field(graph: REVIEWS)
386
+ numberOfReviews: Int! @join__field(graph: REVIEWS)
387
+ goodAddress: Boolean @join__field(graph: REVIEWS, requires: \\"metadata { address }\\")
297
388
  }
298
389
 
299
- type UserMetadata {
300
- address: String
301
- description: String
302
- name: String
390
+ type UserMetadata
391
+ @join__type(graph: ACCOUNTS)
392
+ @join__type(graph: INVENTORY)
393
+ @join__type(graph: REVIEWS)
394
+ {
395
+ name: String @join__field(graph: ACCOUNTS)
396
+ address: String @join__field(graph: ACCOUNTS) @join__field(graph: REVIEWS, external: true)
397
+ description: String @join__field(graph: ACCOUNTS) @join__field(graph: INVENTORY, external: true)
303
398
  }
304
399
 
305
400
  type Van implements Vehicle
306
- @join__owner(graph: PRODUCT)
401
+ @join__implements(graph: PRODUCT, interface: \\"Vehicle\\")
402
+ @join__implements(graph: REVIEWS, interface: \\"Vehicle\\")
307
403
  @join__type(graph: PRODUCT, key: \\"id\\")
308
- @join__type(graph: REVIEWS, key: \\"id\\")
404
+ @join__type(graph: REVIEWS, key: \\"id\\", extension: true)
309
405
  {
406
+ id: String!
310
407
  description: String @join__field(graph: PRODUCT)
311
- id: String! @join__field(graph: PRODUCT)
312
- price: String @join__field(graph: PRODUCT)
408
+ price: String @join__field(graph: PRODUCT) @join__field(graph: REVIEWS, external: true)
313
409
  retailPrice: String @join__field(graph: REVIEWS, requires: \\"price\\")
314
410
  }
315
411
 
316
- interface Vehicle {
317
- description: String
318
- id: String!
319
- price: String
320
- retailPrice: String
321
- }
322
-
323
- enum core__Purpose {
324
- \\"\\"\\"
325
- \`EXECUTION\` features provide metadata necessary to for operation execution.
326
- \\"\\"\\"
327
- EXECUTION
328
-
329
- \\"\\"\\"
330
- \`SECURITY\` features provide metadata necessary to securely resolve fields.
331
- \\"\\"\\"
332
- SECURITY
333
- }
334
-
335
- scalar join__FieldSet
336
-
337
- enum join__Graph {
338
- ACCOUNTS @join__graph(name: \\"accounts\\" url: \\"https://accounts.api.com\\")
339
- BOOKS @join__graph(name: \\"books\\" url: \\"https://books.api.com\\")
340
- DOCUMENTS @join__graph(name: \\"documents\\" url: \\"https://documents.api.com\\")
341
- INVENTORY @join__graph(name: \\"inventory\\" url: \\"https://inventory.api.com\\")
342
- PRODUCT @join__graph(name: \\"product\\" url: \\"https://product.api.com\\")
343
- REVIEWS @join__graph(name: \\"reviews\\" url: \\"https://reviews.api.com\\")
344
- }
345
- ",
412
+ interface Vehicle
413
+ @join__type(graph: PRODUCT)
414
+ @join__type(graph: REVIEWS)
415
+ {
416
+ id: String! @join__field(graph: PRODUCT)
417
+ description: String @join__field(graph: PRODUCT)
418
+ price: String @join__field(graph: PRODUCT)
419
+ retailPrice: String @join__field(graph: REVIEWS)
420
+ }",
346
421
  }
347
422
  `);
348
423
  });
@@ -2,9 +2,9 @@ import gql from 'graphql-tag';
2
2
  import { defineFeature, loadFeature } from 'jest-cucumber';
3
3
  import { DocumentNode } from 'graphql';
4
4
 
5
- import { QueryPlan, BuildQueryPlanOptions } from '@apollo/query-planner';
6
- import { buildOperationContext } from '../operationContext';
5
+ import { QueryPlan } from '@apollo/query-planner';
7
6
  import { getFederatedTestingSchema } from './execution-utils';
7
+ import { operationFromDocument } from '@apollo/federation-internals';
8
8
 
9
9
  const buildQueryPlanFeature = loadFeature(
10
10
  './gateway-js/src/__tests__/build-query-plan.feature'
@@ -18,10 +18,9 @@ const features = [
18
18
  features.forEach((feature) => {
19
19
  defineFeature(feature, (test) => {
20
20
  feature.scenarios.forEach((scenario) => {
21
- test(scenario.title, async ({ given, when, then }) => {
21
+ test(scenario.title, async ({ given, then }) => {
22
22
  let operationDocument: DocumentNode;
23
23
  let queryPlan: QueryPlan;
24
- let options: BuildQueryPlanOptions = { autoFragmentization: false };
25
24
 
26
25
  // throws on composition errors
27
26
  const { schema, queryPlanner } = getFederatedTestingSchema();
@@ -32,21 +31,9 @@ features.forEach((feature) => {
32
31
  })
33
32
  }
34
33
 
35
- const whenUsingAutoFragmentization = () => {
36
- when(/using autofragmentization/i, () => {
37
- options = { autoFragmentization: true };
38
- })
39
- }
40
-
41
34
  const thenQueryPlanShouldBe = () => {
42
35
  then(/^query plan$/i, (expectedQueryPlan: string) => {
43
- queryPlan = queryPlanner.buildQueryPlan(
44
- buildOperationContext({
45
- schema,
46
- operationDocument,
47
- }),
48
- options
49
- );
36
+ queryPlan = queryPlanner.buildQueryPlan(operationFromDocument(schema, operationDocument));
50
37
 
51
38
  const parsedExpectedPlan = JSON.parse(expectedQueryPlan);
52
39
 
@@ -59,7 +46,6 @@ features.forEach((feature) => {
59
46
  scenario.steps.forEach(({ stepText }) => {
60
47
  const title = stepText.toLocaleLowerCase();
61
48
  if (title === "query") givenQuery();
62
- else if (title === "using autofragmentization") whenUsingAutoFragmentization();
63
49
  else if (title === "query plan") thenQueryPlanShouldBe();
64
50
  else throw new Error(`Unrecognized steps used in "build-query-plan.feature"`);
65
51
  });
@@ -192,6 +192,7 @@ describe('core v0.2', () => {
192
192
  const supergraphSdl = `#graphql
193
193
  schema
194
194
  @core(feature: "https://specs.apollo.dev/core/v0.2")
195
+ @core(feature: "https://specs.apollo.dev/join/v0.1", for: EXECUTION)
195
196
  @core(feature: "https://specs.apollo.dev/tag/v0.1")
196
197
  @core(feature: "https://specs.apollo.dev/unsupported-feature/v0.1") {
197
198
  query: Query
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  GraphQLExecutionResult,
3
3
  GraphQLRequestContext,
4
- VariableValues,
5
4
  } from 'apollo-server-types';
6
5
  import { Headers } from 'apollo-server-env';
7
6
  import {
@@ -26,7 +25,6 @@ import {
26
25
  QueryPlanSelectionNode,
27
26
  QueryPlanFieldNode,
28
27
  getResponseName,
29
- toAPISchema
30
28
  } from '@apollo/query-planner';
31
29
  import { deepMerge } from './utilities/deepMerge';
32
30
  import { isNotNullOrUndefined } from './utilities/array';
@@ -94,7 +92,7 @@ export async function executeQueryPlan<TContext>(
94
92
  // the original query.
95
93
  // It is also used to allow execution of introspection queries though.
96
94
  try {
97
- const schema = toAPISchema(operationContext.schema);
95
+ const schema = operationContext.schema;
98
96
  ({ data } = await execute({
99
97
  schema,
100
98
  document: {
@@ -233,10 +231,6 @@ async function executeNode<TContext>(
233
231
  });
234
232
  }
235
233
  case 'Fetch': {
236
- if (shouldSkipFetchNode(node, context.requestContext.request.variables)) {
237
- return new Trace.QueryPlanNode();
238
- }
239
-
240
234
  const traceNode = new Trace.QueryPlanNode.FetchNode({
241
235
  serviceName: node.serviceName,
242
236
  // executeFetch will fill in the other fields if desired.
@@ -257,31 +251,6 @@ async function executeNode<TContext>(
257
251
  }
258
252
  }
259
253
 
260
- export function shouldSkipFetchNode(
261
- node: FetchNode,
262
- variables: VariableValues = {},
263
- ) {
264
- if (!node.inclusionConditions) return false;
265
-
266
- return node.inclusionConditions.every((conditionals) => {
267
- function resolveConditionalValue(conditional: 'skip' | 'include') {
268
- const conditionalType = typeof conditionals[conditional];
269
- if (conditionalType === 'boolean') {
270
- return conditionals[conditional] as boolean;
271
- } else if (conditionalType === 'string') {
272
- return variables[conditionals[conditional] as string] as boolean;
273
- } else {
274
- return null;
275
- }
276
- }
277
-
278
- const includeValue = resolveConditionalValue('include');
279
- const skipValue = resolveConditionalValue('skip');
280
-
281
- return includeValue === false || skipValue === true;
282
- });
283
- }
284
-
285
254
  async function executeFetch<TContext>(
286
255
  context: ExecutionContext<TContext>,
287
256
  fetch: FetchNode,