@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
@@ -1,21 +1,20 @@
1
- import { GraphQLSchema } from 'graphql';
2
- import gql from 'graphql-tag';
3
- import { buildOperationContext } from '../operationContext';
4
- import {
5
- astSerializer,
6
- queryPlanSerializer,
7
- fixturesWithUpdate,
8
- } from 'apollo-federation-integration-testsuite';
1
+ import { astSerializer, queryPlanSerializer } from 'apollo-federation-integration-testsuite';
9
2
  import { getFederatedTestingSchema } from './execution-utils';
10
- import { QueryPlanner, FetchNode } from '@apollo/query-planner';
3
+ import { QueryPlan, QueryPlanner } from '@apollo/query-planner';
4
+ import { Schema, parseOperation } from '@apollo/federation-internals';
11
5
 
12
6
  expect.addSnapshotSerializer(astSerializer);
13
7
  expect.addSnapshotSerializer(queryPlanSerializer);
14
8
 
9
+
15
10
  describe('buildQueryPlan', () => {
16
- let schema: GraphQLSchema;
11
+ let schema: Schema;
17
12
  let queryPlanner: QueryPlanner;
18
13
 
14
+ let buildPlan = (operation: string): QueryPlan => {
15
+ return queryPlanner.buildQueryPlan(parseOperation(schema, operation));
16
+ }
17
+
19
18
  beforeEach(() => {
20
19
  expect(
21
20
  () => ({ schema, queryPlanner } = getFederatedTestingSchema()),
@@ -40,15 +39,7 @@ describe('buildQueryPlan', () => {
40
39
  }
41
40
  }
42
41
  `;
43
-
44
- const operationDocument = gql(operationString);
45
-
46
- const queryPlan = queryPlanner.buildQueryPlan(
47
- buildOperationContext({
48
- schema,
49
- operationDocument,
50
- }),
51
- );
42
+ const queryPlan = buildPlan(operationString);
52
43
 
53
44
  expect(queryPlan).toMatchInlineSnapshot(`
54
45
  QueryPlan {
@@ -78,26 +69,22 @@ describe('buildQueryPlan', () => {
78
69
  const operationString = `#graphql
79
70
  query {
80
71
  me {
81
- name
72
+ name {
73
+ first
74
+ }
82
75
  }
83
76
  }
84
77
  `;
85
78
 
86
- const operationDocument = gql(operationString);
87
-
88
- const queryPlan = queryPlanner.buildQueryPlan(
89
- buildOperationContext({
90
- schema,
91
- operationDocument,
92
- }),
93
- );
94
-
79
+ const queryPlan = buildPlan(operationString);
95
80
  expect(queryPlan).toMatchInlineSnapshot(`
96
81
  QueryPlan {
97
82
  Fetch(service: "accounts") {
98
83
  {
99
84
  me {
100
- name
85
+ name {
86
+ first
87
+ }
101
88
  }
102
89
  }
103
90
  },
@@ -109,7 +96,9 @@ describe('buildQueryPlan', () => {
109
96
  const operationString = `#graphql
110
97
  query {
111
98
  me {
112
- name
99
+ name {
100
+ first
101
+ }
113
102
  }
114
103
  topProducts {
115
104
  name
@@ -117,14 +106,7 @@ describe('buildQueryPlan', () => {
117
106
  }
118
107
  `;
119
108
 
120
- const operationDocument = gql(operationString);
121
-
122
- const queryPlan = queryPlanner.buildQueryPlan(
123
- buildOperationContext({
124
- schema,
125
- operationDocument,
126
- }),
127
- );
109
+ const queryPlan = buildPlan(operationString);
128
110
 
129
111
  expect(queryPlan).toMatchInlineSnapshot(`
130
112
  QueryPlan {
@@ -132,7 +114,9 @@ describe('buildQueryPlan', () => {
132
114
  Fetch(service: "accounts") {
133
115
  {
134
116
  me {
135
- name
117
+ name {
118
+ first
119
+ }
136
120
  }
137
121
  }
138
122
  },
@@ -161,8 +145,6 @@ describe('buildQueryPlan', () => {
161
145
  } =>
162
146
  {
163
147
  ... on Book {
164
- __typename
165
- isbn
166
148
  title
167
149
  year
168
150
  }
@@ -174,9 +156,9 @@ describe('buildQueryPlan', () => {
174
156
  {
175
157
  ... on Book {
176
158
  __typename
177
- isbn
178
159
  title
179
160
  year
161
+ isbn
180
162
  }
181
163
  } =>
182
164
  {
@@ -204,14 +186,7 @@ describe('buildQueryPlan', () => {
204
186
  }
205
187
  `;
206
188
 
207
- const operationDocument = gql(operationString);
208
-
209
- const queryPlan = queryPlanner.buildQueryPlan(
210
- buildOperationContext({
211
- schema,
212
- operationDocument,
213
- }),
214
- );
189
+ const queryPlan = buildPlan(operationString);
215
190
 
216
191
  expect(queryPlan).toMatchInlineSnapshot(`
217
192
  QueryPlan {
@@ -252,8 +227,6 @@ describe('buildQueryPlan', () => {
252
227
  } =>
253
228
  {
254
229
  ... on Book {
255
- __typename
256
- isbn
257
230
  title
258
231
  year
259
232
  }
@@ -265,9 +238,9 @@ describe('buildQueryPlan', () => {
265
238
  {
266
239
  ... on Book {
267
240
  __typename
268
- isbn
269
241
  title
270
242
  year
243
+ isbn
271
244
  }
272
245
  } =>
273
246
  {
@@ -289,8 +262,6 @@ describe('buildQueryPlan', () => {
289
262
  } =>
290
263
  {
291
264
  ... on Book {
292
- __typename
293
- isbn
294
265
  title
295
266
  year
296
267
  }
@@ -302,9 +273,9 @@ describe('buildQueryPlan', () => {
302
273
  {
303
274
  ... on Book {
304
275
  __typename
305
- isbn
306
276
  title
307
277
  year
278
+ isbn
308
279
  }
309
280
  } =>
310
281
  {
@@ -335,14 +306,7 @@ describe('buildQueryPlan', () => {
335
306
  }
336
307
  `;
337
308
 
338
- const operationDocument = gql(operationString);
339
-
340
- const queryPlan = queryPlanner.buildQueryPlan(
341
- buildOperationContext({
342
- schema,
343
- operationDocument,
344
- }),
345
- );
309
+ const queryPlan = buildPlan(operationString);
346
310
 
347
311
  expect(queryPlan).toMatchInlineSnapshot(`
348
312
  QueryPlan {
@@ -377,14 +341,7 @@ describe('buildQueryPlan', () => {
377
341
  }
378
342
  `;
379
343
 
380
- const operationDocument = gql(operationString);
381
-
382
- const queryPlan = queryPlanner.buildQueryPlan(
383
- buildOperationContext({
384
- schema,
385
- operationDocument,
386
- }),
387
- );
344
+ const queryPlan = buildPlan(operationString);
388
345
 
389
346
  expect(queryPlan).toMatchInlineSnapshot(`
390
347
  QueryPlan {
@@ -410,7 +367,9 @@ describe('buildQueryPlan', () => {
410
367
  const operationString = `#graphql
411
368
  query {
412
369
  me {
413
- name
370
+ name {
371
+ first
372
+ }
414
373
  reviews {
415
374
  body
416
375
  }
@@ -418,14 +377,7 @@ describe('buildQueryPlan', () => {
418
377
  }
419
378
  `;
420
379
 
421
- const operationDocument = gql(operationString);
422
-
423
- const queryPlan = queryPlanner.buildQueryPlan(
424
- buildOperationContext({
425
- schema,
426
- operationDocument,
427
- }),
428
- );
380
+ const queryPlan = buildPlan(operationString);
429
381
 
430
382
  expect(queryPlan).toMatchInlineSnapshot(`
431
383
  QueryPlan {
@@ -433,9 +385,11 @@ describe('buildQueryPlan', () => {
433
385
  Fetch(service: "accounts") {
434
386
  {
435
387
  me {
436
- name
437
388
  __typename
438
389
  id
390
+ name {
391
+ first
392
+ }
439
393
  }
440
394
  }
441
395
  },
@@ -473,14 +427,7 @@ describe('buildQueryPlan', () => {
473
427
  }
474
428
  `;
475
429
 
476
- const operationDocument = gql(operationString);
477
-
478
- const queryPlan = queryPlanner.buildQueryPlan(
479
- buildOperationContext({
480
- schema,
481
- operationDocument,
482
- }),
483
- );
430
+ const queryPlan = buildPlan(operationString);
484
431
 
485
432
  expect(queryPlan).toMatchInlineSnapshot(`
486
433
  QueryPlan {
@@ -529,14 +476,7 @@ describe('buildQueryPlan', () => {
529
476
  }
530
477
  `;
531
478
 
532
- const operationDocument = gql(operationString);
533
-
534
- const queryPlan = queryPlanner.buildQueryPlan(
535
- buildOperationContext({
536
- schema,
537
- operationDocument,
538
- }),
539
- );
479
+ const queryPlan = buildPlan(operationString);
540
480
 
541
481
  expect(queryPlan).toMatchInlineSnapshot(`
542
482
  QueryPlan {
@@ -575,25 +515,20 @@ describe('buildQueryPlan', () => {
575
515
 
576
516
  describe(`when requesting a composite field with subfields from another service`, () => {
577
517
  it(`should add key fields to the parent selection set and use a dependent fetch`, () => {
578
- const operationString = `#graphql
518
+ const operationString = `#graphql
579
519
  query {
580
520
  topReviews {
581
521
  body
582
522
  author {
583
- name
523
+ name {
524
+ first
525
+ }
584
526
  }
585
527
  }
586
528
  }
587
529
  `;
588
530
 
589
- const operationDocument = gql(operationString);
590
-
591
- const queryPlan = queryPlanner.buildQueryPlan(
592
- buildOperationContext({
593
- schema,
594
- operationDocument,
595
- }),
596
- );
531
+ const queryPlan = buildPlan(operationString);
597
532
 
598
533
  expect(queryPlan).toMatchInlineSnapshot(`
599
534
  QueryPlan {
@@ -619,7 +554,9 @@ describe('buildQueryPlan', () => {
619
554
  } =>
620
555
  {
621
556
  ... on User {
622
- name
557
+ name {
558
+ first
559
+ }
623
560
  }
624
561
  }
625
562
  },
@@ -639,14 +576,7 @@ describe('buildQueryPlan', () => {
639
576
  }
640
577
  `;
641
578
 
642
- const operationDocument = gql(operationString);
643
-
644
- const queryPlan = queryPlanner.buildQueryPlan(
645
- buildOperationContext({
646
- schema,
647
- operationDocument,
648
- }),
649
- );
579
+ const queryPlan = buildPlan(operationString);
650
580
 
651
581
  expect(queryPlan).toMatchInlineSnapshot(`
652
582
  QueryPlan {
@@ -688,20 +618,15 @@ describe('buildQueryPlan', () => {
688
618
  query {
689
619
  topReviews {
690
620
  author {
691
- name
621
+ name {
622
+ first
623
+ }
692
624
  }
693
625
  }
694
626
  }
695
627
  `;
696
628
 
697
- const operationDocument = gql(operationString);
698
-
699
- const queryPlan = queryPlanner.buildQueryPlan(
700
- buildOperationContext({
701
- schema,
702
- operationDocument,
703
- }),
704
- );
629
+ const queryPlan = buildPlan(operationString);
705
630
 
706
631
  expect(queryPlan).toMatchInlineSnapshot(`
707
632
  QueryPlan {
@@ -726,7 +651,9 @@ describe('buildQueryPlan', () => {
726
651
  } =>
727
652
  {
728
653
  ... on User {
729
- name
654
+ name {
655
+ first
656
+ }
730
657
  }
731
658
  }
732
659
  },
@@ -749,14 +676,7 @@ describe('buildQueryPlan', () => {
749
676
  }
750
677
  `;
751
678
 
752
- const operationDocument = gql(operationString);
753
-
754
- const queryPlan = queryPlanner.buildQueryPlan(
755
- buildOperationContext({
756
- schema,
757
- operationDocument,
758
- }),
759
- );
679
+ const queryPlan = buildPlan(operationString);
760
680
 
761
681
  expect(queryPlan).toMatchInlineSnapshot(`
762
682
  QueryPlan {
@@ -805,14 +725,7 @@ describe('buildQueryPlan', () => {
805
725
  }
806
726
  `;
807
727
 
808
- const operationDocument = gql(operationString);
809
-
810
- const queryPlan = queryPlanner.buildQueryPlan(
811
- buildOperationContext({
812
- schema,
813
- operationDocument,
814
- }),
815
- );
728
+ const queryPlan = buildPlan(operationString);
816
729
 
817
730
  expect(queryPlan).toMatchInlineSnapshot(`
818
731
  QueryPlan {
@@ -820,12 +733,7 @@ describe('buildQueryPlan', () => {
820
733
  {
821
734
  topProducts {
822
735
  __typename
823
- ... on Book {
824
- price
825
- }
826
- ... on Furniture {
827
- price
828
- }
736
+ price
829
737
  }
830
738
  }
831
739
  },
@@ -852,14 +760,7 @@ describe('buildQueryPlan', () => {
852
760
  }
853
761
  `;
854
762
 
855
- const operationDocument = gql(operationString);
856
-
857
- const queryPlan = queryPlanner.buildQueryPlan(
858
- buildOperationContext({
859
- schema,
860
- operationDocument,
861
- }),
862
- );
763
+ const queryPlan = buildPlan(operationString);
863
764
 
864
765
  expect(queryPlan).toMatchInlineSnapshot(`
865
766
  QueryPlan {
@@ -899,14 +800,7 @@ describe('buildQueryPlan', () => {
899
800
  }
900
801
  `;
901
802
 
902
- const operationDocument = gql(operationString);
903
-
904
- const queryPlan = queryPlanner.buildQueryPlan(
905
- buildOperationContext({
906
- schema,
907
- operationDocument,
908
- }),
909
- );
803
+ const queryPlan = buildPlan(operationString);
910
804
 
911
805
  expect(queryPlan).toMatchInlineSnapshot(`
912
806
  QueryPlan {
@@ -927,7 +821,7 @@ describe('buildQueryPlan', () => {
927
821
  `);
928
822
  });
929
823
 
930
- it(`should preserve type conditions for value types`, () => {
824
+ it(`eliminate unecessary type conditions`, () => {
931
825
  const operationString = `#graphql
932
826
  query {
933
827
  body {
@@ -940,14 +834,7 @@ describe('buildQueryPlan', () => {
940
834
  }
941
835
  `;
942
836
 
943
- const operationDocument = gql(operationString);
944
-
945
- const queryPlan = queryPlanner.buildQueryPlan(
946
- buildOperationContext({
947
- schema,
948
- operationDocument,
949
- }),
950
- );
837
+ const queryPlan = buildPlan(operationString);
951
838
 
952
839
  expect(queryPlan).toMatchInlineSnapshot(`
953
840
  QueryPlan {
@@ -956,9 +843,7 @@ describe('buildQueryPlan', () => {
956
843
  body {
957
844
  __typename
958
845
  ... on Image {
959
- ... on NamedObject {
960
- name
961
- }
846
+ name
962
847
  }
963
848
  }
964
849
  }
@@ -969,7 +854,7 @@ describe('buildQueryPlan', () => {
969
854
 
970
855
  it(`should preserve directives on inline fragments even if the fragment is otherwise useless`, () => {
971
856
  const operationString = `#graphql
972
- query myQuery($b: Boolean) {
857
+ query myQuery($b: Boolean!) {
973
858
  body {
974
859
  ... on Image {
975
860
  ... on NamedObject @include(if: $b) {
@@ -980,14 +865,7 @@ describe('buildQueryPlan', () => {
980
865
  }
981
866
  `;
982
867
 
983
- const operationDocument = gql(operationString);
984
-
985
- const queryPlan = queryPlanner.buildQueryPlan(
986
- buildOperationContext({
987
- schema,
988
- operationDocument,
989
- }),
990
- );
868
+ const queryPlan = buildPlan(operationString);
991
869
 
992
870
  expect(queryPlan).toMatchInlineSnapshot(`
993
871
  QueryPlan {
@@ -1023,14 +901,7 @@ describe('buildQueryPlan', () => {
1023
901
  }
1024
902
  `;
1025
903
 
1026
- const operationDocument = gql(operationString);
1027
-
1028
- const queryPlan = queryPlanner.buildQueryPlan(
1029
- buildOperationContext({
1030
- schema,
1031
- operationDocument,
1032
- }),
1033
- );
904
+ const queryPlan = buildPlan(operationString);
1034
905
 
1035
906
  expect(queryPlan).toMatchInlineSnapshot(`
1036
907
  QueryPlan {
@@ -1039,13 +910,12 @@ describe('buildQueryPlan', () => {
1039
910
  {
1040
911
  topProducts {
1041
912
  __typename
913
+ price
1042
914
  ... on Book {
1043
- price
1044
915
  __typename
1045
916
  isbn
1046
917
  }
1047
918
  ... on Furniture {
1048
- price
1049
919
  __typename
1050
920
  upc
1051
921
  }
@@ -1097,14 +967,7 @@ describe('buildQueryPlan', () => {
1097
967
  }
1098
968
  `;
1099
969
 
1100
- const operationDocument = gql(operationString);
1101
-
1102
- const queryPlan = queryPlanner.buildQueryPlan(
1103
- buildOperationContext({
1104
- schema,
1105
- operationDocument,
1106
- }),
1107
- );
970
+ const queryPlan = buildPlan(operationString);
1108
971
 
1109
972
  expect(queryPlan).toMatchInlineSnapshot(`
1110
973
  QueryPlan {
@@ -1141,7 +1004,7 @@ describe('buildQueryPlan', () => {
1141
1004
  `);
1142
1005
  });
1143
1006
 
1144
- it(`interface inside interface should expand into possible types only`, () => {
1007
+ it(`interface inside interface should not type explode if possible`, () => {
1145
1008
  const operationString = `#graphql
1146
1009
  query {
1147
1010
  product(upc: "") {
@@ -1152,14 +1015,7 @@ describe('buildQueryPlan', () => {
1152
1015
  }
1153
1016
  `;
1154
1017
 
1155
- const operationDocument = gql(operationString);
1156
-
1157
- const queryPlan = queryPlanner.buildQueryPlan(
1158
- buildOperationContext({
1159
- schema,
1160
- operationDocument,
1161
- }),
1162
- );
1018
+ const queryPlan = buildPlan(operationString);
1163
1019
 
1164
1020
  expect(queryPlan).toMatchInlineSnapshot(`
1165
1021
  QueryPlan {
@@ -1167,15 +1023,9 @@ describe('buildQueryPlan', () => {
1167
1023
  {
1168
1024
  product(upc: "") {
1169
1025
  __typename
1170
- ... on Book {
1171
- details {
1172
- country
1173
- }
1174
- }
1175
- ... on Furniture {
1176
- details {
1177
- country
1178
- }
1026
+ details {
1027
+ __typename
1028
+ country
1179
1029
  }
1180
1030
  }
1181
1031
  }
@@ -1184,342 +1034,6 @@ describe('buildQueryPlan', () => {
1184
1034
  `);
1185
1035
  });
1186
1036
 
1187
- describe(`experimental compression to downstream services`, () => {
1188
- it(`should generate fragments internally to downstream requests`, () => {
1189
- const operationString = `#graphql
1190
- query {
1191
- topReviews {
1192
- body
1193
- author
1194
- product {
1195
- name
1196
- price
1197
- details {
1198
- country
1199
- }
1200
- }
1201
- }
1202
- }
1203
- `;
1204
-
1205
- const operationDocument = gql(operationString);
1206
-
1207
- const queryPlan = queryPlanner.buildQueryPlan(
1208
- buildOperationContext({
1209
- schema,
1210
- operationDocument,
1211
- }),
1212
- { autoFragmentization: true },
1213
- );
1214
-
1215
- expect(queryPlan).toMatchInlineSnapshot(`
1216
- QueryPlan {
1217
- Sequence {
1218
- Fetch(service: "reviews") {
1219
- {
1220
- topReviews {
1221
- ...__QueryPlanFragment_1__
1222
- }
1223
- }
1224
-
1225
- fragment __QueryPlanFragment_1__ on Review {
1226
- body
1227
- author
1228
- product {
1229
- ...__QueryPlanFragment_0__
1230
- }
1231
- }
1232
-
1233
- fragment __QueryPlanFragment_0__ on Product {
1234
- __typename
1235
- ... on Book {
1236
- __typename
1237
- isbn
1238
- }
1239
- ... on Furniture {
1240
- __typename
1241
- upc
1242
- }
1243
- }
1244
- },
1245
- Parallel {
1246
- Sequence {
1247
- Flatten(path: "topReviews.@.product") {
1248
- Fetch(service: "books") {
1249
- {
1250
- ... on Book {
1251
- __typename
1252
- isbn
1253
- }
1254
- } =>
1255
- {
1256
- ... on Book {
1257
- __typename
1258
- isbn
1259
- title
1260
- year
1261
- }
1262
- }
1263
- },
1264
- },
1265
- Flatten(path: "topReviews.@.product") {
1266
- Fetch(service: "product") {
1267
- {
1268
- ... on Book {
1269
- __typename
1270
- isbn
1271
- title
1272
- year
1273
- }
1274
- } =>
1275
- {
1276
- ... on Book {
1277
- name
1278
- }
1279
- }
1280
- },
1281
- },
1282
- },
1283
- Flatten(path: "topReviews.@.product") {
1284
- Fetch(service: "product") {
1285
- {
1286
- ... on Furniture {
1287
- __typename
1288
- upc
1289
- }
1290
- ... on Book {
1291
- __typename
1292
- isbn
1293
- }
1294
- } =>
1295
- {
1296
- ... on Furniture {
1297
- name
1298
- price
1299
- details {
1300
- country
1301
- }
1302
- }
1303
- ... on Book {
1304
- price
1305
- details {
1306
- country
1307
- }
1308
- }
1309
- }
1310
- },
1311
- },
1312
- },
1313
- },
1314
- }
1315
- `);
1316
- });
1317
-
1318
- it(`shouldn't generate fragments for selection sets of length 2 or less`, () => {
1319
- const operationString = `#graphql
1320
- query {
1321
- topReviews {
1322
- body
1323
- author
1324
- }
1325
- }
1326
- `;
1327
-
1328
- const operationDocument = gql(operationString);
1329
-
1330
- const queryPlan = queryPlanner.buildQueryPlan(
1331
- buildOperationContext({
1332
- schema,
1333
- operationDocument,
1334
- }),
1335
- { autoFragmentization: true },
1336
- );
1337
-
1338
- expect(queryPlan).toMatchInlineSnapshot(`
1339
- QueryPlan {
1340
- Fetch(service: "reviews") {
1341
- {
1342
- topReviews {
1343
- body
1344
- author
1345
- }
1346
- }
1347
- },
1348
- }
1349
- `);
1350
- });
1351
-
1352
- it(`should generate fragments for selection sets of length 3 or greater`, () => {
1353
- const operationString = `#graphql
1354
- query {
1355
- topReviews {
1356
- id
1357
- body
1358
- author
1359
- }
1360
- }
1361
- `;
1362
-
1363
- const operationDocument = gql(operationString);
1364
-
1365
- const queryPlan = queryPlanner.buildQueryPlan(
1366
- buildOperationContext({
1367
- schema,
1368
- operationDocument,
1369
- }),
1370
- { autoFragmentization: true },
1371
- );
1372
-
1373
- expect(queryPlan).toMatchInlineSnapshot(`
1374
- QueryPlan {
1375
- Fetch(service: "reviews") {
1376
- {
1377
- topReviews {
1378
- ...__QueryPlanFragment_0__
1379
- }
1380
- }
1381
-
1382
- fragment __QueryPlanFragment_0__ on Review {
1383
- id
1384
- body
1385
- author
1386
- }
1387
- },
1388
- }
1389
- `);
1390
- });
1391
-
1392
- it(`should generate fragments correctly when aliases are used`, () => {
1393
- const operationString = `#graphql
1394
- query {
1395
- reviews: topReviews {
1396
- content: body
1397
- author
1398
- product {
1399
- name
1400
- cost: price
1401
- details {
1402
- origin: country
1403
- }
1404
- }
1405
- }
1406
- }
1407
- `;
1408
-
1409
- const operationDocument = gql(operationString);
1410
-
1411
- const queryPlan = queryPlanner.buildQueryPlan(
1412
- buildOperationContext({
1413
- schema,
1414
- operationDocument,
1415
- }),
1416
- { autoFragmentization: true },
1417
- );
1418
-
1419
- expect(queryPlan).toMatchInlineSnapshot(`
1420
- QueryPlan {
1421
- Sequence {
1422
- Fetch(service: "reviews") {
1423
- {
1424
- reviews: topReviews {
1425
- ...__QueryPlanFragment_1__
1426
- }
1427
- }
1428
-
1429
- fragment __QueryPlanFragment_1__ on Review {
1430
- content: body
1431
- author
1432
- product {
1433
- ...__QueryPlanFragment_0__
1434
- }
1435
- }
1436
-
1437
- fragment __QueryPlanFragment_0__ on Product {
1438
- __typename
1439
- ... on Book {
1440
- __typename
1441
- isbn
1442
- }
1443
- ... on Furniture {
1444
- __typename
1445
- upc
1446
- }
1447
- }
1448
- },
1449
- Parallel {
1450
- Sequence {
1451
- Flatten(path: "reviews.@.product") {
1452
- Fetch(service: "books") {
1453
- {
1454
- ... on Book {
1455
- __typename
1456
- isbn
1457
- }
1458
- } =>
1459
- {
1460
- ... on Book {
1461
- __typename
1462
- isbn
1463
- title
1464
- year
1465
- }
1466
- }
1467
- },
1468
- },
1469
- Flatten(path: "reviews.@.product") {
1470
- Fetch(service: "product") {
1471
- {
1472
- ... on Book {
1473
- __typename
1474
- isbn
1475
- title
1476
- year
1477
- }
1478
- } =>
1479
- {
1480
- ... on Book {
1481
- name
1482
- }
1483
- }
1484
- },
1485
- },
1486
- },
1487
- Flatten(path: "reviews.@.product") {
1488
- Fetch(service: "product") {
1489
- {
1490
- ... on Furniture {
1491
- __typename
1492
- upc
1493
- }
1494
- ... on Book {
1495
- __typename
1496
- isbn
1497
- }
1498
- } =>
1499
- {
1500
- ... on Furniture {
1501
- name
1502
- cost: price
1503
- details {
1504
- origin: country
1505
- }
1506
- }
1507
- ... on Book {
1508
- cost: price
1509
- details {
1510
- origin: country
1511
- }
1512
- }
1513
- }
1514
- },
1515
- },
1516
- },
1517
- },
1518
- }
1519
- `);
1520
- });
1521
- });
1522
-
1523
1037
  it(`should properly expand nested unions with inline fragments`, () => {
1524
1038
  const operationString = `#graphql
1525
1039
  query {
@@ -1548,14 +1062,7 @@ describe('buildQueryPlan', () => {
1548
1062
  }
1549
1063
  `;
1550
1064
 
1551
- const operationDocument = gql(operationString);
1552
-
1553
- const queryPlan = queryPlanner.buildQueryPlan(
1554
- buildOperationContext({
1555
- schema,
1556
- operationDocument,
1557
- }),
1558
- );
1065
+ const queryPlan = buildPlan(operationString);
1559
1066
 
1560
1067
  expect(queryPlan).toMatchInlineSnapshot(`
1561
1068
  QueryPlan {
@@ -1585,13 +1092,6 @@ describe('buildQueryPlan', () => {
1585
1092
  const operationString = `#graphql
1586
1093
  query {
1587
1094
  body {
1588
- ... on Image {
1589
- ... on Text {
1590
- attributes {
1591
- bold
1592
- }
1593
- }
1594
- }
1595
1095
  ... on Body {
1596
1096
  ... on Text {
1597
1097
  attributes {
@@ -1610,14 +1110,7 @@ describe('buildQueryPlan', () => {
1610
1110
  }
1611
1111
  `;
1612
1112
 
1613
- const operationDocument = gql(operationString);
1614
-
1615
- const queryPlan = queryPlanner.buildQueryPlan(
1616
- buildOperationContext({
1617
- schema,
1618
- operationDocument,
1619
- }),
1620
- );
1113
+ const queryPlan = buildPlan(operationString);
1621
1114
 
1622
1115
  expect(queryPlan).toMatchInlineSnapshot(`
1623
1116
  QueryPlan {
@@ -1649,9 +1142,6 @@ describe('buildQueryPlan', () => {
1649
1142
 
1650
1143
  query {
1651
1144
  body {
1652
- ... on Image {
1653
- ...TextFragment
1654
- }
1655
1145
  ... on Body {
1656
1146
  ...TextFragment
1657
1147
  }
@@ -1660,14 +1150,7 @@ describe('buildQueryPlan', () => {
1660
1150
  }
1661
1151
  `;
1662
1152
 
1663
- const operationDocument = gql(operationString);
1664
-
1665
- const queryPlan = queryPlanner.buildQueryPlan(
1666
- buildOperationContext({
1667
- schema,
1668
- operationDocument,
1669
- }),
1670
- );
1153
+ const queryPlan = buildPlan(operationString);
1671
1154
 
1672
1155
  expect(queryPlan).toMatchInlineSnapshot(`
1673
1156
  QueryPlan {
@@ -1688,251 +1171,4 @@ describe('buildQueryPlan', () => {
1688
1171
  `);
1689
1172
  });
1690
1173
  });
1691
-
1692
- describe('top-level @skip/@include behavior', () => {
1693
- beforeEach(() => {
1694
- ({ schema, queryPlanner } =
1695
- getFederatedTestingSchema(fixturesWithUpdate));
1696
- });
1697
-
1698
- function getQueryPlan(operation: string) {
1699
- const operationDocument = gql(operation);
1700
-
1701
- return queryPlanner.buildQueryPlan(
1702
- buildOperationContext({
1703
- schema,
1704
- operationDocument,
1705
- }),
1706
- );
1707
- }
1708
-
1709
- it('simple skip', () => {
1710
- const operation = `#graphql
1711
- query {
1712
- topReviews @skip(if: true) {
1713
- body
1714
- }
1715
- }
1716
- `;
1717
-
1718
- expect(
1719
- (getQueryPlan(operation).node as FetchNode).inclusionConditions,
1720
- ).toEqual([{ skip: true, include: null }]);
1721
- });
1722
-
1723
- it('simple include', () => {
1724
- const operation = `#graphql
1725
- query {
1726
- topReviews @include(if: false) {
1727
- body
1728
- }
1729
- }
1730
- `;
1731
-
1732
- expect(
1733
- (getQueryPlan(operation).node as FetchNode).inclusionConditions,
1734
- ).toEqual([{ include: false, skip: null }]);
1735
- });
1736
-
1737
- it('simple include with variables', () => {
1738
- const operation = `#graphql
1739
- query {
1740
- topReviews @include(if: $shouldInclude) {
1741
- body
1742
- }
1743
- }
1744
- `;
1745
-
1746
- expect(
1747
- (getQueryPlan(operation).node as FetchNode).inclusionConditions,
1748
- ).toEqual([{ include: 'shouldInclude', skip: null }]);
1749
- });
1750
-
1751
- it('simple skip with variables', () => {
1752
- const operation = `#graphql
1753
- query {
1754
- topReviews @skip(if: $shouldSkip) {
1755
- body
1756
- }
1757
- }
1758
- `;
1759
-
1760
- expect(
1761
- (getQueryPlan(operation).node as FetchNode).inclusionConditions,
1762
- ).toEqual([{ skip: 'shouldSkip', include: null }]);
1763
- });
1764
-
1765
- it('not all top-levels have conditionals', () => {
1766
- const operation = `#graphql
1767
- query {
1768
- topReviews @skip(if: $shouldSkip) {
1769
- body
1770
- }
1771
- review(id: "1") {
1772
- body
1773
- }
1774
- }
1775
- `;
1776
-
1777
- expect(
1778
- (getQueryPlan(operation).node as FetchNode).inclusionConditions,
1779
- ).toBeUndefined();
1780
- });
1781
-
1782
- it('all top-levels have conditionals', () => {
1783
- const operation = `#graphql
1784
- query {
1785
- topReviews @skip(if: $shouldSkip) {
1786
- body
1787
- }
1788
- review(id: "1") @skip(if: true) {
1789
- body
1790
- }
1791
- }
1792
- `;
1793
-
1794
- expect(
1795
- (getQueryPlan(operation).node as FetchNode).inclusionConditions,
1796
- ).toEqual([
1797
- { skip: 'shouldSkip', include: null },
1798
- { skip: true, include: null },
1799
- ]);
1800
- });
1801
-
1802
- it('all top-levels use literals (include case)', () => {
1803
- const operation = `#graphql
1804
- query {
1805
- topReviews @skip(if: false) {
1806
- body
1807
- }
1808
- review(id: "1") @include(if: true) {
1809
- body
1810
- }
1811
- }
1812
- `;
1813
-
1814
- expect(
1815
- (getQueryPlan(operation).node as FetchNode).inclusionConditions,
1816
- ).toBeUndefined();
1817
- });
1818
-
1819
- it('all top-levels use literals (skip case)', () => {
1820
- const operation = `#graphql
1821
- query {
1822
- topReviews @skip(if: true) {
1823
- body
1824
- }
1825
- review(id: "1") @include(if: false) {
1826
- body
1827
- }
1828
- }
1829
- `;
1830
-
1831
- expect(
1832
- (getQueryPlan(operation).node as FetchNode).inclusionConditions,
1833
- ).toEqual([
1834
- { skip: true, include: null },
1835
- { include: false, skip: null },
1836
- ]);
1837
- });
1838
-
1839
- it('skip: false, include: false', () => {
1840
- const operation = `#graphql
1841
- query {
1842
- topReviews @skip(if: false) @include(if: false) {
1843
- body
1844
- }
1845
- }
1846
- `;
1847
-
1848
- expect(
1849
- (getQueryPlan(operation).node as FetchNode).inclusionConditions,
1850
- ).toEqual([{ skip: false, include: false }]);
1851
- });
1852
-
1853
- it('skip: false, include: true', () => {
1854
- const operation = `#graphql
1855
- query {
1856
- topReviews @skip(if: false) @include(if: true) {
1857
- body
1858
- }
1859
- }
1860
- `;
1861
-
1862
- expect(
1863
- (getQueryPlan(operation).node as FetchNode).inclusionConditions,
1864
- ).toBeUndefined();
1865
- });
1866
-
1867
- it('skip: true, include: false', () => {
1868
- const operation = `#graphql
1869
- query {
1870
- topReviews @skip(if: true) @include(if: false) {
1871
- body
1872
- }
1873
- }
1874
- `;
1875
-
1876
- expect(
1877
- (getQueryPlan(operation).node as FetchNode).inclusionConditions,
1878
- ).toEqual([{ skip: true, include: false }]);
1879
- });
1880
-
1881
- it('skip: true, include: true', () => {
1882
- const operation = `#graphql
1883
- query {
1884
- topReviews @skip(if: true) @include(if: true) {
1885
- body
1886
- }
1887
- }
1888
- `;
1889
-
1890
- expect(
1891
- (getQueryPlan(operation).node as FetchNode).inclusionConditions,
1892
- ).toEqual([{ skip: true, include: true }]);
1893
- });
1894
-
1895
- describe.skip('known limitations', () => {
1896
- it('conditionals on top-level fragment spreads are captured', () => {
1897
- const operation = `#graphql
1898
- query {
1899
- ...TopReviews @skip(if: $shouldSkip)
1900
- }
1901
-
1902
- fragment TopReviews on Query {
1903
- topReviews {
1904
- body
1905
- }
1906
- }
1907
- `;
1908
-
1909
- expect(
1910
- (getQueryPlan(operation).node as FetchNode).inclusionConditions,
1911
- ).toEqual([{ skip: 'shouldSkip', include: null }]);
1912
- });
1913
-
1914
- it('conditionals on top-level inline fragments are captured', () => {
1915
- const operation = `#graphql
1916
- query {
1917
- ... on Query @skip(if: $shouldSkip) {
1918
- topReviews {
1919
- body
1920
- }
1921
- }
1922
- }
1923
- `;
1924
-
1925
- expect(
1926
- (getQueryPlan(operation).node as FetchNode).inclusionConditions,
1927
- ).toEqual([{ skip: 'shouldSkip', include: null }]);
1928
- });
1929
-
1930
- it.todo(
1931
- 'deeply-nested conditionals within fragment spreads are captured',
1932
- );
1933
- it.todo(
1934
- 'deeply-nested conditionals within inline fragments are captured',
1935
- );
1936
- });
1937
- });
1938
1174
  });