@apollo/gateway 2.4.5 → 2.4.6

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 (64) hide show
  1. package/dist/__generated__/graphqlTypes.d.ts +19 -1
  2. package/dist/__generated__/graphqlTypes.d.ts.map +1 -1
  3. package/dist/__generated__/graphqlTypes.js +1 -0
  4. package/dist/__generated__/graphqlTypes.js.map +1 -1
  5. package/package.json +4 -4
  6. package/src/__generated__/graphqlTypes.ts +33 -2
  7. package/src/__mocks__/tsconfig.json +0 -7
  8. package/src/__tests__/.gitkeep +0 -0
  9. package/src/__tests__/CucumberREADME.md +0 -96
  10. package/src/__tests__/build-query-plan.feature +0 -1471
  11. package/src/__tests__/buildQueryPlan.test.ts +0 -1225
  12. package/src/__tests__/executeQueryPlan.conditions.test.ts +0 -1488
  13. package/src/__tests__/executeQueryPlan.introspection.test.ts +0 -140
  14. package/src/__tests__/executeQueryPlan.test.ts +0 -6140
  15. package/src/__tests__/execution-utils.ts +0 -124
  16. package/src/__tests__/gateway/__snapshots__/opentelemetry.test.ts.snap +0 -195
  17. package/src/__tests__/gateway/buildService.test.ts +0 -249
  18. package/src/__tests__/gateway/endToEnd.test.ts +0 -486
  19. package/src/__tests__/gateway/executor.test.ts +0 -96
  20. package/src/__tests__/gateway/extensions.test.ts +0 -37
  21. package/src/__tests__/gateway/lifecycle-hooks.test.ts +0 -239
  22. package/src/__tests__/gateway/opentelemetry.test.ts +0 -123
  23. package/src/__tests__/gateway/queryPlanCache.test.ts +0 -231
  24. package/src/__tests__/gateway/queryPlannerConfig.test.ts +0 -101
  25. package/src/__tests__/gateway/reporting.test.ts +0 -616
  26. package/src/__tests__/gateway/supergraphSdl.test.ts +0 -396
  27. package/src/__tests__/gateway/testUtils.ts +0 -89
  28. package/src/__tests__/integration/abstract-types.test.ts +0 -1861
  29. package/src/__tests__/integration/aliases.test.ts +0 -180
  30. package/src/__tests__/integration/boolean.test.ts +0 -279
  31. package/src/__tests__/integration/complex-key.test.ts +0 -197
  32. package/src/__tests__/integration/configuration.test.ts +0 -404
  33. package/src/__tests__/integration/custom-directives.test.ts +0 -174
  34. package/src/__tests__/integration/execution-style.test.ts +0 -35
  35. package/src/__tests__/integration/fragments.test.ts +0 -237
  36. package/src/__tests__/integration/list-key.test.ts +0 -128
  37. package/src/__tests__/integration/logger.test.ts +0 -122
  38. package/src/__tests__/integration/managed.test.ts +0 -319
  39. package/src/__tests__/integration/merge-arrays.test.ts +0 -34
  40. package/src/__tests__/integration/multiple-key.test.ts +0 -327
  41. package/src/__tests__/integration/mutations.test.ts +0 -287
  42. package/src/__tests__/integration/networkRequests.test.ts +0 -542
  43. package/src/__tests__/integration/nockMocks.ts +0 -157
  44. package/src/__tests__/integration/provides.test.ts +0 -77
  45. package/src/__tests__/integration/requires.test.ts +0 -359
  46. package/src/__tests__/integration/scope.test.ts +0 -557
  47. package/src/__tests__/integration/single-service.test.ts +0 -119
  48. package/src/__tests__/integration/unions.test.ts +0 -79
  49. package/src/__tests__/integration/value-types.test.ts +0 -382
  50. package/src/__tests__/integration/variables.test.ts +0 -120
  51. package/src/__tests__/nockAssertions.ts +0 -20
  52. package/src/__tests__/queryPlanCucumber.test.ts +0 -55
  53. package/src/__tests__/resultShaping.test.ts +0 -605
  54. package/src/__tests__/testSetup.ts +0 -1
  55. package/src/__tests__/tsconfig.json +0 -8
  56. package/src/core/__tests__/core.test.ts +0 -412
  57. package/src/datasources/__tests__/LocalGraphQLDataSource.test.ts +0 -51
  58. package/src/datasources/__tests__/RemoteGraphQLDataSource.test.ts +0 -574
  59. package/src/schema-helper/__tests__/addExtensions.test.ts +0 -70
  60. package/src/supergraphManagers/IntrospectAndCompose/__tests__/IntrospectAndCompose.test.ts +0 -364
  61. package/src/supergraphManagers/IntrospectAndCompose/__tests__/loadServicesFromRemoteEndpoint.test.ts +0 -40
  62. package/src/supergraphManagers/UplinkSupergraphManager/__tests__/UplinkSupergraphManager.test.ts +0 -65
  63. package/src/supergraphManagers/UplinkSupergraphManager/__tests__/loadSupergraphSdlFromStorage.test.ts +0 -511
  64. package/src/utilities/__tests__/deepMerge.test.ts +0 -77
@@ -1,1861 +0,0 @@
1
- import { execute } from '../execution-utils';
2
-
3
- import { astSerializer, fed2gql as gql, queryPlanSerializer } from 'apollo-federation-integration-testsuite';
4
-
5
- expect.addSnapshotSerializer(astSerializer);
6
- expect.addSnapshotSerializer(queryPlanSerializer);
7
-
8
- it('handles an abstract type from the base service', async () => {
9
- const query = `#graphql
10
- query GetProduct($upc: String!) {
11
- product(upc: $upc) {
12
- upc
13
- name
14
- price
15
- }
16
- }
17
- `;
18
-
19
- const upc = '1';
20
- const { data, queryPlan } = await execute({
21
- query,
22
- variables: { upc },
23
- });
24
-
25
- expect(data).toEqual({
26
- product: {
27
- upc,
28
- name: 'Table',
29
- price: '899',
30
- },
31
- });
32
-
33
- expect(queryPlan).toCallService('product');
34
- expect(queryPlan).toMatchInlineSnapshot(`
35
- QueryPlan {
36
- Sequence {
37
- Fetch(service: "product") {
38
- {
39
- product(upc: $upc) {
40
- __typename
41
- upc
42
- ... on Book {
43
- __typename
44
- isbn
45
- }
46
- ... on Furniture {
47
- name
48
- }
49
- price
50
- }
51
- }
52
- },
53
- Flatten(path: "product") {
54
- Fetch(service: "books") {
55
- {
56
- ... on Book {
57
- __typename
58
- isbn
59
- }
60
- } =>
61
- {
62
- ... on Book {
63
- title
64
- year
65
- }
66
- }
67
- },
68
- },
69
- Flatten(path: "product") {
70
- Fetch(service: "product") {
71
- {
72
- ... on Book {
73
- __typename
74
- title
75
- year
76
- isbn
77
- }
78
- } =>
79
- {
80
- ... on Book {
81
- name
82
- }
83
- }
84
- },
85
- },
86
- },
87
- }
88
- `);
89
- });
90
-
91
- it('can request fields on extended interfaces', async () => {
92
- const query = `#graphql
93
- query GetProduct($upc: String!) {
94
- product(upc: $upc) {
95
- inStock
96
- }
97
- }
98
- `;
99
-
100
- const upc = '1';
101
-
102
- const { data, queryPlan } = await execute({
103
- query,
104
- variables: { upc },
105
- });
106
-
107
- expect(data).toEqual({ product: { inStock: true } });
108
- expect(queryPlan).toCallService('product');
109
- expect(queryPlan).toCallService('inventory');
110
- expect(queryPlan).toMatchInlineSnapshot(`
111
- QueryPlan {
112
- Sequence {
113
- Fetch(service: "product") {
114
- {
115
- product(upc: $upc) {
116
- __typename
117
- ... on Book {
118
- __typename
119
- isbn
120
- }
121
- ... on Furniture {
122
- __typename
123
- sku
124
- }
125
- }
126
- }
127
- },
128
- Flatten(path: "product") {
129
- Fetch(service: "inventory") {
130
- {
131
- ... on Book {
132
- __typename
133
- isbn
134
- }
135
- ... on Furniture {
136
- __typename
137
- sku
138
- }
139
- } =>
140
- {
141
- ... on Book {
142
- inStock
143
- }
144
- ... on Furniture {
145
- inStock
146
- }
147
- }
148
- },
149
- },
150
- },
151
- }
152
- `);
153
- });
154
-
155
- it('can request fields on extended types that implement an interface', async () => {
156
- const query = `#graphql
157
- query GetProduct($upc: String!) {
158
- product(upc: $upc) {
159
- inStock
160
- ... on Furniture {
161
- isHeavy
162
- }
163
- }
164
- }
165
- `;
166
-
167
- const upc = '1';
168
- const { data, queryPlan } = await execute({
169
- query,
170
- variables: { upc },
171
- });
172
-
173
- expect(data).toEqual({ product: { inStock: true, isHeavy: false } });
174
- expect(queryPlan).toCallService('product');
175
- expect(queryPlan).toCallService('inventory');
176
- expect(queryPlan).toMatchInlineSnapshot(`
177
- QueryPlan {
178
- Sequence {
179
- Fetch(service: "product") {
180
- {
181
- product(upc: $upc) {
182
- __typename
183
- ... on Book {
184
- __typename
185
- isbn
186
- }
187
- ... on Furniture {
188
- __typename
189
- sku
190
- }
191
- }
192
- }
193
- },
194
- Flatten(path: "product") {
195
- Fetch(service: "inventory") {
196
- {
197
- ... on Book {
198
- __typename
199
- isbn
200
- }
201
- ... on Furniture {
202
- __typename
203
- sku
204
- }
205
- } =>
206
- {
207
- ... on Book {
208
- inStock
209
- }
210
- ... on Furniture {
211
- inStock
212
- isHeavy
213
- }
214
- }
215
- },
216
- },
217
- },
218
- }
219
- `);
220
- });
221
-
222
- it('prunes unfilled type conditions', async () => {
223
- const query = `#graphql
224
- query GetProduct($upc: String!) {
225
- product(upc: $upc) {
226
- inStock
227
- ... on Furniture {
228
- isHeavy
229
- }
230
- ... on Book {
231
- isCheckedOut
232
- }
233
- }
234
- }
235
- `;
236
-
237
- const upc = '1';
238
- const { data, queryPlan } = await execute({
239
- query,
240
- variables: { upc },
241
- });
242
-
243
- expect(data).toEqual({ product: { inStock: true, isHeavy: false } });
244
- expect(queryPlan).toCallService('product');
245
- expect(queryPlan).toCallService('inventory');
246
- expect(queryPlan).toMatchInlineSnapshot(`
247
- QueryPlan {
248
- Sequence {
249
- Fetch(service: "product") {
250
- {
251
- product(upc: $upc) {
252
- __typename
253
- ... on Book {
254
- __typename
255
- isbn
256
- }
257
- ... on Furniture {
258
- __typename
259
- sku
260
- }
261
- }
262
- }
263
- },
264
- Flatten(path: "product") {
265
- Fetch(service: "inventory") {
266
- {
267
- ... on Book {
268
- __typename
269
- isbn
270
- }
271
- ... on Furniture {
272
- __typename
273
- sku
274
- }
275
- } =>
276
- {
277
- ... on Book {
278
- inStock
279
- isCheckedOut
280
- }
281
- ... on Furniture {
282
- inStock
283
- isHeavy
284
- }
285
- }
286
- },
287
- },
288
- },
289
- }
290
- `);
291
- });
292
-
293
- it('fetches interfaces returned from other services', async () => {
294
- const query = `#graphql
295
- query GetUserAndProducts {
296
- me {
297
- reviews {
298
- product {
299
- price
300
- ... on Book {
301
- title
302
- }
303
- }
304
- }
305
- }
306
- }
307
- `;
308
-
309
- const { data, queryPlan } = await execute({
310
- query,
311
- });
312
-
313
- expect(data).toEqual({
314
- me: {
315
- reviews: [
316
- { product: { price: '899' } },
317
- { product: { price: '1299' } },
318
- { product: { price: '49', title: 'Design Patterns' } },
319
- ],
320
- },
321
- });
322
-
323
- expect(queryPlan).toCallService('accounts');
324
- expect(queryPlan).toCallService('reviews');
325
- expect(queryPlan).toCallService('product');
326
- expect(queryPlan).toMatchInlineSnapshot(`
327
- QueryPlan {
328
- Sequence {
329
- Fetch(service: "accounts") {
330
- {
331
- me {
332
- __typename
333
- id
334
- }
335
- }
336
- },
337
- Flatten(path: "me") {
338
- Fetch(service: "reviews") {
339
- {
340
- ... on User {
341
- __typename
342
- id
343
- }
344
- } =>
345
- {
346
- ... on User {
347
- reviews {
348
- product {
349
- __typename
350
- ... on Book {
351
- __typename
352
- isbn
353
- }
354
- ... on Furniture {
355
- __typename
356
- upc
357
- }
358
- }
359
- }
360
- }
361
- }
362
- },
363
- },
364
- Parallel {
365
- Flatten(path: "me.reviews.@.product") {
366
- Fetch(service: "books") {
367
- {
368
- ... on Book {
369
- __typename
370
- isbn
371
- }
372
- } =>
373
- {
374
- ... on Book {
375
- title
376
- }
377
- }
378
- },
379
- },
380
- Flatten(path: "me.reviews.@.product") {
381
- Fetch(service: "product") {
382
- {
383
- ... on Book {
384
- __typename
385
- isbn
386
- }
387
- ... on Furniture {
388
- __typename
389
- upc
390
- }
391
- } =>
392
- {
393
- ... on Book {
394
- price
395
- }
396
- ... on Furniture {
397
- price
398
- }
399
- }
400
- },
401
- },
402
- },
403
- },
404
- }
405
- `);
406
- });
407
-
408
- it('fetches composite fields from a foreign type casted to an interface [@provides field]', async () => {
409
- const query = `#graphql
410
- query GetUserAndProducts {
411
- me {
412
- reviews {
413
- product {
414
- price
415
- ... on Book {
416
- name
417
- }
418
- }
419
- }
420
- }
421
- }
422
- `;
423
-
424
- const { data, queryPlan } = await execute({
425
- query,
426
- });
427
-
428
- expect(data).toEqual({
429
- me: {
430
- reviews: [
431
- { product: { price: '899' } },
432
- { product: { price: '1299' } },
433
- { product: { price: '49', name: 'Design Patterns (1995)' } },
434
- ],
435
- },
436
- });
437
-
438
- expect(queryPlan).toCallService('accounts');
439
- expect(queryPlan).toCallService('reviews');
440
- expect(queryPlan).toCallService('product');
441
- expect(queryPlan).toMatchInlineSnapshot(`
442
- QueryPlan {
443
- Sequence {
444
- Fetch(service: "accounts") {
445
- {
446
- me {
447
- __typename
448
- id
449
- }
450
- }
451
- },
452
- Flatten(path: "me") {
453
- Fetch(service: "reviews") {
454
- {
455
- ... on User {
456
- __typename
457
- id
458
- }
459
- } =>
460
- {
461
- ... on User {
462
- reviews {
463
- product {
464
- __typename
465
- ... on Book {
466
- __typename
467
- isbn
468
- }
469
- ... on Furniture {
470
- __typename
471
- upc
472
- }
473
- }
474
- }
475
- }
476
- }
477
- },
478
- },
479
- Parallel {
480
- Flatten(path: "me.reviews.@.product") {
481
- Fetch(service: "product") {
482
- {
483
- ... on Book {
484
- __typename
485
- isbn
486
- }
487
- ... on Furniture {
488
- __typename
489
- upc
490
- }
491
- } =>
492
- {
493
- ... on Book {
494
- price
495
- }
496
- ... on Furniture {
497
- price
498
- }
499
- }
500
- },
501
- },
502
- Sequence {
503
- Flatten(path: "me.reviews.@.product") {
504
- Fetch(service: "books") {
505
- {
506
- ... on Book {
507
- __typename
508
- isbn
509
- }
510
- } =>
511
- {
512
- ... on Book {
513
- title
514
- year
515
- }
516
- }
517
- },
518
- },
519
- Flatten(path: "me.reviews.@.product") {
520
- Fetch(service: "product") {
521
- {
522
- ... on Book {
523
- __typename
524
- title
525
- year
526
- isbn
527
- }
528
- } =>
529
- {
530
- ... on Book {
531
- name
532
- }
533
- }
534
- },
535
- },
536
- },
537
- },
538
- },
539
- }
540
- `);
541
- });
542
-
543
- it('allows for extending an interface from another service with fields', async () => {
544
- const query = `#graphql
545
- query GetProduct($upc: String!) {
546
- product(upc: $upc) {
547
- reviews {
548
- body
549
- }
550
- }
551
- }
552
- `;
553
-
554
- const upc = '1';
555
- const { data, queryPlan } = await execute({
556
- query,
557
- variables: { upc },
558
- });
559
-
560
- expect(data).toEqual({
561
- product: {
562
- reviews: [{ body: 'Love it!' }, { body: 'Prefer something else.' }],
563
- },
564
- });
565
-
566
- expect(queryPlan).toCallService('reviews');
567
- expect(queryPlan).toCallService('product');
568
- expect(queryPlan).toMatchInlineSnapshot(`
569
- QueryPlan {
570
- Sequence {
571
- Fetch(service: "product") {
572
- {
573
- product(upc: $upc) {
574
- __typename
575
- ... on Book {
576
- __typename
577
- isbn
578
- }
579
- ... on Furniture {
580
- __typename
581
- upc
582
- }
583
- }
584
- }
585
- },
586
- Flatten(path: "product") {
587
- Fetch(service: "reviews") {
588
- {
589
- ... on Book {
590
- __typename
591
- isbn
592
- }
593
- ... on Furniture {
594
- __typename
595
- upc
596
- }
597
- } =>
598
- {
599
- ... on Book {
600
- reviews {
601
- body
602
- }
603
- }
604
- ... on Furniture {
605
- reviews {
606
- body
607
- }
608
- }
609
- }
610
- },
611
- },
612
- },
613
- }
614
- `);
615
- });
616
-
617
- describe('unions', () => {
618
- it('handles unions from the same service', async () => {
619
- const query = `#graphql
620
- query GetUserAndProducts {
621
- me {
622
- reviews {
623
- product {
624
- price
625
- ... on Furniture {
626
- brand {
627
- ... on Ikea {
628
- asile
629
- }
630
- ... on Amazon {
631
- referrer
632
- }
633
- }
634
- }
635
- }
636
- }
637
- }
638
- }
639
- `;
640
-
641
- const { data, queryPlan } = await execute({
642
- query,
643
- });
644
-
645
- expect(data).toEqual({
646
- me: {
647
- reviews: [
648
- { product: { price: '899', brand: { asile: 10 } } },
649
- {
650
- product: {
651
- price: '1299',
652
- brand: { referrer: 'https://canopy.co' },
653
- },
654
- },
655
- { product: { price: '49' } },
656
- ],
657
- },
658
- });
659
-
660
- expect(queryPlan).toCallService('accounts');
661
- expect(queryPlan).toCallService('reviews');
662
- expect(queryPlan).toCallService('product');
663
- expect(queryPlan).toMatchInlineSnapshot(`
664
- QueryPlan {
665
- Sequence {
666
- Fetch(service: "accounts") {
667
- {
668
- me {
669
- __typename
670
- id
671
- }
672
- }
673
- },
674
- Flatten(path: "me") {
675
- Fetch(service: "reviews") {
676
- {
677
- ... on User {
678
- __typename
679
- id
680
- }
681
- } =>
682
- {
683
- ... on User {
684
- reviews {
685
- product {
686
- __typename
687
- ... on Book {
688
- __typename
689
- isbn
690
- }
691
- ... on Furniture {
692
- __typename
693
- upc
694
- }
695
- }
696
- }
697
- }
698
- }
699
- },
700
- },
701
- Flatten(path: "me.reviews.@.product") {
702
- Fetch(service: "product") {
703
- {
704
- ... on Book {
705
- __typename
706
- isbn
707
- }
708
- ... on Furniture {
709
- __typename
710
- upc
711
- }
712
- } =>
713
- {
714
- ... on Book {
715
- price
716
- }
717
- ... on Furniture {
718
- price
719
- brand {
720
- __typename
721
- ... on Ikea {
722
- asile
723
- }
724
- ... on Amazon {
725
- referrer
726
- }
727
- }
728
- }
729
- }
730
- },
731
- },
732
- },
733
- }
734
- `);
735
- });
736
-
737
- it("doesn't expand interfaces with inline type conditions if all possibilities are fufilled by one service", async () => {
738
- const query = `#graphql
739
- query GetProducts {
740
- topProducts {
741
- name
742
- }
743
- }
744
- `;
745
-
746
- const { queryPlan, errors } = await execute({ query }, [
747
- {
748
- name: 'products',
749
- typeDefs: gql`
750
- extend type Query {
751
- topProducts: [Product]
752
- }
753
-
754
- interface Product {
755
- name: String
756
- }
757
-
758
- type Shoe implements Product {
759
- name: String
760
- }
761
-
762
- type Car implements Product {
763
- name: String
764
- }
765
- `,
766
- },
767
- ]);
768
-
769
- expect(errors).toBeUndefined();
770
- expect(queryPlan).toMatchInlineSnapshot(`
771
- QueryPlan {
772
- Fetch(service: "products") {
773
- {
774
- topProducts {
775
- __typename
776
- name
777
- }
778
- }
779
- },
780
- }
781
- `);
782
- });
783
-
784
- // FIXME: turn back on when extending unions is supported in composition
785
- it.todo('fetches unions across services');
786
- // async () => {
787
- // const query = gql`
788
- // query GetUserAndProducts {
789
- // me {
790
- // account {
791
- // ... on LibraryAccount {
792
- // library {
793
- // name
794
- // }
795
- // }
796
- // ... on SMSAccount {
797
- // number
798
- // }
799
- // }
800
- // }
801
- // }
802
- // `;
803
-
804
- // const { data, queryPlan } = await execute(
805
- // {
806
- // query,
807
- // },
808
- // );
809
-
810
- // expect(data).toEqual({
811
- // me: {
812
- // account: {
813
- // library: {
814
- // name: 'NYC Public Library',
815
- // },
816
- // },
817
- // },
818
- // });
819
-
820
- // expect(queryPlan).toCallService('accounts');
821
- // expect(queryPlan).toCallService('books');
822
- // });
823
- });
824
-
825
- describe("doesn't result in duplicate fetches", () => {
826
- it("when exploding types", async () => {
827
- const query = `#graphql
828
- query {
829
- topProducts {
830
- name
831
- price
832
- reviews {
833
- author {
834
- name
835
- username
836
- }
837
- body
838
- id
839
- }
840
- }
841
- }
842
- `;
843
-
844
- const { queryPlan, errors } = await execute({ query }, [
845
- {
846
- name: 'accounts',
847
- typeDefs: gql`
848
- type User @key(fields: "id") {
849
- id: ID!
850
- name: String
851
- username: String @shareable
852
- }
853
- `,
854
- },
855
- {
856
- name: 'products',
857
- typeDefs: gql`
858
- type Book implements Product @key(fields: "isbn") {
859
- isbn: String!
860
- title: String
861
- year: Int
862
- name: String
863
- price: Int
864
- }
865
- type TV implements Product @key(fields: "id") {
866
- id: String!
867
- title: String
868
- year: Int
869
- name: String
870
- price: Int
871
- }
872
- type Computer implements Product @key(fields: "id") {
873
- id: String!
874
- title: String
875
- year: Int
876
- name: String
877
- price: Int
878
- }
879
- type Furniture implements Product @key(fields: "sku") {
880
- sku: String!
881
- name: String
882
- price: Int
883
- weight: Int
884
- }
885
- interface Product {
886
- name: String
887
- price: Int
888
- }
889
- extend type Query {
890
- topProducts: [Product]
891
- }
892
- `,
893
- },
894
- {
895
- name: 'reviews',
896
- typeDefs: gql`
897
- extend type Book implements Product @key(fields: "isbn") {
898
- isbn: String! @external
899
- reviews: [Review]
900
- }
901
- extend type TV implements Product @key(fields: "id") {
902
- id: String! @external
903
- reviews: [Review]
904
- }
905
- extend type Computer implements Product @key(fields: "id") {
906
- id: String! @external
907
- reviews: [Review]
908
- }
909
- extend type Furniture implements Product @key(fields: "sku") {
910
- sku: String! @external
911
- reviews: [Review]
912
- }
913
- extend interface Product {
914
- reviews: [Review]
915
- }
916
- type Review @key(fields: "id") {
917
- id: ID!
918
- body: String
919
- author: User @provides(fields: "username")
920
- product: Product
921
- }
922
- extend type User @key(fields: "id") {
923
- id: ID! @external
924
- username: String @external
925
- reviews: [Review]
926
- }
927
- `,
928
- },
929
- ]);
930
-
931
- expect(errors).toBeUndefined();
932
- expect(queryPlan).toMatchInlineSnapshot(`
933
- QueryPlan {
934
- Sequence {
935
- Fetch(service: "products") {
936
- {
937
- topProducts {
938
- __typename
939
- name
940
- price
941
- ... on Book {
942
- __typename
943
- isbn
944
- }
945
- ... on TV {
946
- __typename
947
- id
948
- }
949
- ... on Computer {
950
- __typename
951
- id
952
- }
953
- ... on Furniture {
954
- __typename
955
- sku
956
- }
957
- }
958
- }
959
- },
960
- Flatten(path: "topProducts.@") {
961
- Fetch(service: "reviews") {
962
- {
963
- ... on Book {
964
- __typename
965
- isbn
966
- }
967
- ... on TV {
968
- __typename
969
- id
970
- }
971
- ... on Computer {
972
- __typename
973
- id
974
- }
975
- ... on Furniture {
976
- __typename
977
- sku
978
- }
979
- } =>
980
- {
981
- ... on Book {
982
- reviews {
983
- author {
984
- __typename
985
- id
986
- username
987
- }
988
- body
989
- id
990
- }
991
- }
992
- ... on TV {
993
- reviews {
994
- author {
995
- __typename
996
- id
997
- username
998
- }
999
- body
1000
- id
1001
- }
1002
- }
1003
- ... on Computer {
1004
- reviews {
1005
- author {
1006
- __typename
1007
- id
1008
- username
1009
- }
1010
- body
1011
- id
1012
- }
1013
- }
1014
- ... on Furniture {
1015
- reviews {
1016
- author {
1017
- __typename
1018
- id
1019
- username
1020
- }
1021
- body
1022
- id
1023
- }
1024
- }
1025
- }
1026
- },
1027
- },
1028
- Flatten(path: "topProducts.@.reviews.@.author") {
1029
- Fetch(service: "accounts") {
1030
- {
1031
- ... on User {
1032
- __typename
1033
- id
1034
- }
1035
- } =>
1036
- {
1037
- ... on User {
1038
- name
1039
- }
1040
- }
1041
- },
1042
- },
1043
- },
1044
- }
1045
- `);
1046
- });
1047
-
1048
- it("when including the same nested fields under different type conditions", async () => {
1049
- const query = `#graphql
1050
- query {
1051
- topProducts {
1052
- ... on Book {
1053
- name
1054
- price
1055
- reviews {
1056
- author {
1057
- name
1058
- username
1059
- }
1060
- body
1061
- id
1062
- }
1063
- }
1064
- ... on TV {
1065
- name
1066
- price
1067
- reviews {
1068
- author {
1069
- name
1070
- username
1071
- }
1072
- body
1073
- id
1074
- }
1075
- }
1076
- }
1077
- }
1078
- `;
1079
-
1080
- const { queryPlan, errors } = await execute({ query }, [
1081
- {
1082
- name: 'accounts',
1083
- typeDefs: gql`
1084
- type User @key(fields: "id") {
1085
- id: ID!
1086
- name: String
1087
- username: String @shareable
1088
- }
1089
- `,
1090
- },
1091
- {
1092
- name: 'products',
1093
- typeDefs: gql`
1094
- type Book implements Product @key(fields: "isbn") {
1095
- isbn: String!
1096
- title: String
1097
- year: Int
1098
- name: String
1099
- price: Int
1100
- }
1101
- type TV implements Product @key(fields: "id") {
1102
- id: String!
1103
- title: String
1104
- year: Int
1105
- name: String
1106
- price: Int
1107
- }
1108
- type Computer implements Product @key(fields: "id") {
1109
- id: String!
1110
- title: String
1111
- year: Int
1112
- name: String
1113
- price: Int
1114
- }
1115
- type Furniture implements Product @key(fields: "sku") {
1116
- sku: String!
1117
- name: String
1118
- price: Int
1119
- weight: Int
1120
- }
1121
- interface Product {
1122
- name: String
1123
- price: Int
1124
- }
1125
- extend type Query {
1126
- topProducts: [Product]
1127
- }
1128
- `,
1129
- },
1130
- {
1131
- name: 'reviews',
1132
- typeDefs: gql`
1133
- extend type Book implements Product @key(fields: "isbn") {
1134
- isbn: String! @external
1135
- reviews: [Review]
1136
- }
1137
- extend type TV implements Product @key(fields: "id") {
1138
- id: String! @external
1139
- reviews: [Review]
1140
- }
1141
- extend type Computer implements Product @key(fields: "id") {
1142
- id: String! @external
1143
- reviews: [Review]
1144
- }
1145
- extend type Furniture implements Product @key(fields: "sku") {
1146
- sku: String! @external
1147
- reviews: [Review]
1148
- }
1149
- extend interface Product {
1150
- reviews: [Review]
1151
- }
1152
- type Review @key(fields: "id") {
1153
- id: ID!
1154
- body: String
1155
- author: User @provides(fields: "username")
1156
- product: Product
1157
- }
1158
- extend type User @key(fields: "id") {
1159
- id: ID! @external
1160
- username: String @external
1161
- reviews: [Review]
1162
- }
1163
- `,
1164
- },
1165
- ]);
1166
-
1167
- expect(errors).toBeUndefined();
1168
- expect(queryPlan).toMatchInlineSnapshot(`
1169
- QueryPlan {
1170
- Sequence {
1171
- Fetch(service: "products") {
1172
- {
1173
- topProducts {
1174
- __typename
1175
- ... on Book {
1176
- __typename
1177
- isbn
1178
- name
1179
- price
1180
- }
1181
- ... on TV {
1182
- __typename
1183
- id
1184
- name
1185
- price
1186
- }
1187
- }
1188
- }
1189
- },
1190
- Flatten(path: "topProducts.@") {
1191
- Fetch(service: "reviews") {
1192
- {
1193
- ... on Book {
1194
- __typename
1195
- isbn
1196
- }
1197
- ... on TV {
1198
- __typename
1199
- id
1200
- }
1201
- } =>
1202
- {
1203
- ... on Book {
1204
- reviews {
1205
- author {
1206
- __typename
1207
- id
1208
- username
1209
- }
1210
- body
1211
- id
1212
- }
1213
- }
1214
- ... on TV {
1215
- reviews {
1216
- author {
1217
- __typename
1218
- id
1219
- username
1220
- }
1221
- body
1222
- id
1223
- }
1224
- }
1225
- }
1226
- },
1227
- },
1228
- Flatten(path: "topProducts.@.reviews.@.author") {
1229
- Fetch(service: "accounts") {
1230
- {
1231
- ... on User {
1232
- __typename
1233
- id
1234
- }
1235
- } =>
1236
- {
1237
- ... on User {
1238
- name
1239
- }
1240
- }
1241
- },
1242
- },
1243
- },
1244
- }
1245
- `);
1246
- });
1247
-
1248
- it('when including multiple nested fields to the same service under different type conditions', async () => {
1249
- const query = `#graphql
1250
- query {
1251
- topProducts {
1252
- ... on Book {
1253
- name
1254
- price
1255
- reviews {
1256
- author {
1257
- name
1258
- username
1259
- }
1260
- editor {
1261
- name
1262
- username
1263
- }
1264
- body
1265
- id
1266
- }
1267
- }
1268
- ... on TV {
1269
- name
1270
- price
1271
- reviews {
1272
- author {
1273
- name
1274
- username
1275
- }
1276
- editor {
1277
- name
1278
- username
1279
- }
1280
- body
1281
- id
1282
- }
1283
- }
1284
- }
1285
- }
1286
- `;
1287
-
1288
- const { queryPlan, errors } = await execute({ query }, [
1289
- {
1290
- name: 'accounts',
1291
- typeDefs: gql`
1292
- type User @key(fields: "id") {
1293
- id: ID!
1294
- name: String
1295
- username: String @shareable
1296
- }
1297
- `,
1298
- },
1299
- {
1300
- name: 'products',
1301
- typeDefs: gql`
1302
- type Book implements Product @key(fields: "isbn") {
1303
- isbn: String!
1304
- title: String
1305
- year: Int
1306
- name: String
1307
- price: Int
1308
- }
1309
- type TV implements Product @key(fields: "id") {
1310
- id: String!
1311
- title: String
1312
- year: Int
1313
- name: String
1314
- price: Int
1315
- }
1316
- type Computer implements Product @key(fields: "id") {
1317
- id: String!
1318
- title: String
1319
- year: Int
1320
- name: String
1321
- price: Int
1322
- }
1323
- type Furniture implements Product @key(fields: "sku") {
1324
- sku: String!
1325
- name: String
1326
- price: Int
1327
- weight: Int
1328
- }
1329
- interface Product {
1330
- name: String
1331
- price: Int
1332
- }
1333
- extend type Query {
1334
- topProducts: [Product]
1335
- }
1336
- `,
1337
- },
1338
- {
1339
- name: 'reviews',
1340
- typeDefs: gql`
1341
- extend type Book implements Product @key(fields: "isbn") {
1342
- isbn: String! @external
1343
- reviews: [Review]
1344
- }
1345
- extend type TV implements Product @key(fields: "id") {
1346
- id: String! @external
1347
- reviews: [Review]
1348
- }
1349
- extend type Computer implements Product @key(fields: "id") {
1350
- id: String! @external
1351
- reviews: [Review]
1352
- }
1353
- extend type Furniture implements Product @key(fields: "sku") {
1354
- sku: String! @external
1355
- reviews: [Review]
1356
- }
1357
- extend interface Product {
1358
- reviews: [Review]
1359
- }
1360
- type Review @key(fields: "id") {
1361
- id: ID!
1362
- body: String
1363
- author: User @provides(fields: "username")
1364
- editor: User @provides(fields: "username")
1365
- product: Product
1366
- }
1367
- extend type User @key(fields: "id") {
1368
- id: ID! @external
1369
- username: String @external
1370
- reviews: [Review]
1371
- }
1372
- `,
1373
- },
1374
- ]);
1375
-
1376
- expect(errors).toBeUndefined();
1377
- expect(queryPlan).toMatchInlineSnapshot(`
1378
- QueryPlan {
1379
- Sequence {
1380
- Fetch(service: "products") {
1381
- {
1382
- topProducts {
1383
- __typename
1384
- ... on Book {
1385
- __typename
1386
- isbn
1387
- name
1388
- price
1389
- }
1390
- ... on TV {
1391
- __typename
1392
- id
1393
- name
1394
- price
1395
- }
1396
- }
1397
- }
1398
- },
1399
- Flatten(path: "topProducts.@") {
1400
- Fetch(service: "reviews") {
1401
- {
1402
- ... on Book {
1403
- __typename
1404
- isbn
1405
- }
1406
- ... on TV {
1407
- __typename
1408
- id
1409
- }
1410
- } =>
1411
- {
1412
- ... on Book {
1413
- reviews {
1414
- author {
1415
- __typename
1416
- id
1417
- username
1418
- }
1419
- editor {
1420
- __typename
1421
- id
1422
- username
1423
- }
1424
- body
1425
- id
1426
- }
1427
- }
1428
- ... on TV {
1429
- reviews {
1430
- author {
1431
- __typename
1432
- id
1433
- username
1434
- }
1435
- editor {
1436
- __typename
1437
- id
1438
- username
1439
- }
1440
- body
1441
- id
1442
- }
1443
- }
1444
- }
1445
- },
1446
- },
1447
- Parallel {
1448
- Flatten(path: "topProducts.@.reviews.@.author") {
1449
- Fetch(service: "accounts") {
1450
- {
1451
- ... on User {
1452
- __typename
1453
- id
1454
- }
1455
- } =>
1456
- {
1457
- ... on User {
1458
- name
1459
- }
1460
- }
1461
- },
1462
- },
1463
- Flatten(path: "topProducts.@.reviews.@.editor") {
1464
- Fetch(service: "accounts") {
1465
- {
1466
- ... on User {
1467
- __typename
1468
- id
1469
- }
1470
- } =>
1471
- {
1472
- ... on User {
1473
- name
1474
- }
1475
- }
1476
- },
1477
- },
1478
- },
1479
- },
1480
- }
1481
- `);
1482
- });
1483
-
1484
- it('when exploding types through multiple levels', async () => {
1485
- const query = `#graphql
1486
- query {
1487
- productsByCategory {
1488
- name
1489
- ... on BookCategory {
1490
- items {
1491
- ...ProductReviews
1492
- }
1493
- }
1494
- ... on FurnitureCategory {
1495
- items {
1496
- ...ProductReviews
1497
- }
1498
- }
1499
- }
1500
- }
1501
-
1502
- fragment ProductReviews on Product {
1503
- reviews {
1504
- body
1505
- }
1506
- }
1507
- `;
1508
-
1509
- const { queryPlan, errors } = await execute({ query }, [
1510
- {
1511
- name: 'accounts',
1512
- typeDefs: gql`
1513
- type User @key(fields: "id") {
1514
- id: ID!
1515
- name: String
1516
- username: String @shareable
1517
- }
1518
- `,
1519
- },
1520
- {
1521
- name: 'products',
1522
- typeDefs: gql`
1523
- type Book implements Product @key(fields: "isbn") {
1524
- isbn: String!
1525
- title: String
1526
- year: Int
1527
- name: String
1528
- price: Int
1529
- }
1530
-
1531
- type Furniture implements Product @key(fields: "sku") {
1532
- sku: String!
1533
- name: String
1534
- price: Int
1535
- weight: Int
1536
- }
1537
-
1538
- interface Product {
1539
- name: String
1540
- price: Int
1541
- }
1542
-
1543
- extend type Query {
1544
- productsByCategory: [ProductCategory]
1545
- }
1546
-
1547
- interface ProductCategory {
1548
- name: String!
1549
- }
1550
-
1551
- type BookCategory implements ProductCategory {
1552
- name: String!
1553
- items: [Book]
1554
- }
1555
-
1556
- type FurnitureCategory implements ProductCategory {
1557
- name: String!
1558
- items: [Furniture]
1559
- }
1560
- `,
1561
- },
1562
- {
1563
- name: 'reviews',
1564
- typeDefs: gql`
1565
- extend type Book implements Product @key(fields: "isbn") {
1566
- isbn: String! @external
1567
- reviews: [Review]
1568
- }
1569
- extend type Furniture implements Product @key(fields: "sku") {
1570
- sku: String! @external
1571
- reviews: [Review]
1572
- }
1573
- extend interface Product {
1574
- reviews: [Review]
1575
- }
1576
- type Review @key(fields: "id") {
1577
- id: ID!
1578
- body: String
1579
- author: User @provides(fields: "username")
1580
- product: Product
1581
- }
1582
- extend type User @key(fields: "id") {
1583
- id: ID! @external
1584
- username: String @external
1585
- reviews: [Review]
1586
- }
1587
- `,
1588
- },
1589
- ]);
1590
-
1591
- expect(errors).toBeUndefined();
1592
- expect(queryPlan).toMatchInlineSnapshot(`
1593
- QueryPlan {
1594
- Sequence {
1595
- Fetch(service: "products") {
1596
- {
1597
- productsByCategory {
1598
- __typename
1599
- name
1600
- ... on BookCategory {
1601
- items {
1602
- __typename
1603
- isbn
1604
- }
1605
- }
1606
- ... on FurnitureCategory {
1607
- items {
1608
- __typename
1609
- sku
1610
- }
1611
- }
1612
- }
1613
- }
1614
- },
1615
- Flatten(path: "productsByCategory.@.items.@") {
1616
- Fetch(service: "reviews") {
1617
- {
1618
- ... on Book {
1619
- __typename
1620
- isbn
1621
- }
1622
- ... on Furniture {
1623
- __typename
1624
- sku
1625
- }
1626
- } =>
1627
- {
1628
- ... on Book {
1629
- ...ProductReviews
1630
- }
1631
- ... on Furniture {
1632
- ...ProductReviews
1633
- }
1634
- }
1635
-
1636
- fragment ProductReviews on Product {
1637
- reviews {
1638
- body
1639
- }
1640
- }
1641
- },
1642
- },
1643
- },
1644
- }
1645
- `);
1646
- });
1647
-
1648
- it("when including the same nested fields under different type conditions that are split between services", async () => {
1649
- const query = `#graphql
1650
- query {
1651
- topProducts {
1652
- ... on Book {
1653
- name
1654
- price
1655
- reviews {
1656
- author {
1657
- name
1658
- username
1659
- }
1660
- body
1661
- id
1662
- }
1663
- }
1664
- ... on TV {
1665
- name
1666
- price
1667
- reviews {
1668
- author {
1669
- name
1670
- username
1671
- }
1672
- body
1673
- id
1674
- }
1675
- }
1676
- }
1677
- }
1678
- `;
1679
-
1680
- const { queryPlan, errors } = await execute({ query }, [
1681
- {
1682
- name: 'accounts',
1683
- typeDefs: gql`
1684
- type User @key(fields: "id") {
1685
- id: ID!
1686
- name: String
1687
- username: String @shareable
1688
- }
1689
- `,
1690
- },
1691
- {
1692
- name: 'products',
1693
- typeDefs: gql`
1694
- type Book implements Product @key(fields: "isbn") {
1695
- isbn: String!
1696
- title: String
1697
- year: Int
1698
- name: String
1699
- price: Int
1700
- }
1701
- type TV implements Product @key(fields: "id") {
1702
- id: String!
1703
- title: String
1704
- year: Int
1705
- name: String
1706
- price: Int
1707
- }
1708
- interface Product {
1709
- name: String
1710
- price: Int
1711
- }
1712
- extend type Query {
1713
- topProducts: [Product]
1714
- }
1715
- `,
1716
- },
1717
- {
1718
- name: 'reviews',
1719
- typeDefs: gql`
1720
- extend type TV implements Product @key(fields: "id") {
1721
- id: String! @external
1722
- reviews: [Review]
1723
- }
1724
- extend interface Product {
1725
- reviews: [Review]
1726
- }
1727
- type Review @key(fields: "id") {
1728
- id: ID!
1729
- body: String
1730
- author: User @provides(fields: "username")
1731
- product: Product
1732
- }
1733
- extend type User @key(fields: "id") {
1734
- id: ID! @external
1735
- username: String @external
1736
- reviews: [Review]
1737
- }
1738
- `,
1739
- },
1740
- {
1741
- name: 'books',
1742
- typeDefs: gql`
1743
- extend type Book @key(fields: "isbn") {
1744
- isbn: String! @external
1745
- reviews: [Review]
1746
- }
1747
- extend type Review @key(fields: "id") {
1748
- id: ID! @external
1749
- }
1750
- `,
1751
- },
1752
- ]);
1753
-
1754
- expect(errors).toBeUndefined();
1755
- expect(queryPlan).toMatchInlineSnapshot(`
1756
- QueryPlan {
1757
- Sequence {
1758
- Fetch(service: "products") {
1759
- {
1760
- topProducts {
1761
- __typename
1762
- ... on Book {
1763
- __typename
1764
- isbn
1765
- name
1766
- price
1767
- }
1768
- ... on TV {
1769
- __typename
1770
- id
1771
- name
1772
- price
1773
- }
1774
- }
1775
- }
1776
- },
1777
- Parallel {
1778
- Sequence {
1779
- Flatten(path: "topProducts.@") {
1780
- Fetch(service: "books") {
1781
- {
1782
- ... on Book {
1783
- __typename
1784
- isbn
1785
- }
1786
- } =>
1787
- {
1788
- ... on Book {
1789
- reviews {
1790
- __typename
1791
- id
1792
- }
1793
- }
1794
- }
1795
- },
1796
- },
1797
- Flatten(path: "topProducts.@.reviews.@") {
1798
- Fetch(service: "reviews") {
1799
- {
1800
- ... on Review {
1801
- __typename
1802
- id
1803
- }
1804
- } =>
1805
- {
1806
- ... on Review {
1807
- author {
1808
- __typename
1809
- id
1810
- username
1811
- }
1812
- body
1813
- }
1814
- }
1815
- },
1816
- },
1817
- },
1818
- Flatten(path: "topProducts.@") {
1819
- Fetch(service: "reviews") {
1820
- {
1821
- ... on TV {
1822
- __typename
1823
- id
1824
- }
1825
- } =>
1826
- {
1827
- ... on TV {
1828
- reviews {
1829
- author {
1830
- __typename
1831
- id
1832
- username
1833
- }
1834
- body
1835
- id
1836
- }
1837
- }
1838
- }
1839
- },
1840
- },
1841
- },
1842
- Flatten(path: "topProducts.@.reviews.@.author") {
1843
- Fetch(service: "accounts") {
1844
- {
1845
- ... on User {
1846
- __typename
1847
- id
1848
- }
1849
- } =>
1850
- {
1851
- ... on User {
1852
- name
1853
- }
1854
- }
1855
- },
1856
- },
1857
- },
1858
- }
1859
- `);
1860
- });
1861
- });