@apollo/gateway 2.0.0-alpha.4 → 2.0.0-preview.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -5
- package/dist/__generated__/graphqlTypes.d.ts +3 -0
- package/dist/__generated__/graphqlTypes.d.ts.map +1 -1
- package/dist/__generated__/graphqlTypes.js.map +1 -1
- package/dist/executeQueryPlan.d.ts.map +1 -1
- package/dist/executeQueryPlan.js +4 -3
- package/dist/executeQueryPlan.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -3
- package/dist/index.js.map +1 -1
- package/dist/schema-helper/index.js +5 -1
- package/dist/schema-helper/index.js.map +1 -1
- package/dist/supergraphManagers/IntrospectAndCompose/index.js.map +1 -1
- package/dist/supergraphManagers/LegacyFetcher/index.js +1 -1
- package/dist/supergraphManagers/LegacyFetcher/index.js.map +1 -1
- package/dist/supergraphManagers/LocalCompose/index.js +1 -1
- package/dist/supergraphManagers/LocalCompose/index.js.map +1 -1
- package/dist/supergraphManagers/UplinkFetcher/index.d.ts +1 -0
- package/dist/supergraphManagers/UplinkFetcher/index.d.ts.map +1 -1
- package/dist/supergraphManagers/UplinkFetcher/index.js +2 -0
- package/dist/supergraphManagers/UplinkFetcher/index.js.map +1 -1
- package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.d.ts +5 -1
- package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.d.ts.map +1 -1
- package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.js +29 -31
- package/dist/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.js.map +1 -1
- package/dist/supergraphManagers/index.d.ts +1 -0
- package/dist/supergraphManagers/index.d.ts.map +1 -1
- package/dist/supergraphManagers/index.js +3 -1
- package/dist/supergraphManagers/index.js.map +1 -1
- package/package.json +8 -7
- package/src/__generated__/graphqlTypes.ts +10 -1
- package/src/__tests__/build-query-plan.feature +84 -16
- package/src/__tests__/executeQueryPlan.test.ts +256 -1
- package/src/__tests__/gateway/lifecycle-hooks.test.ts +8 -2
- package/src/__tests__/gateway/supergraphSdl.test.ts +5 -3
- package/src/__tests__/integration/abstract-types.test.ts +6 -7
- package/src/__tests__/integration/nockMocks.ts +3 -2
- package/src/__tests__/integration/value-types.test.ts +4 -4
- package/src/executeQueryPlan.ts +4 -0
- package/src/index.ts +4 -1
- package/src/supergraphManagers/LegacyFetcher/index.ts +1 -1
- package/src/supergraphManagers/LocalCompose/index.ts +1 -1
- package/src/supergraphManagers/UplinkFetcher/__tests__/loadSupergraphSdlFromStorage.test.ts +82 -28
- package/src/supergraphManagers/UplinkFetcher/index.ts +2 -0
- package/src/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.ts +31 -26
- package/src/supergraphManagers/index.ts +1 -0
|
@@ -19,7 +19,7 @@ import { QueryPlan, QueryPlanner } from '@apollo/query-planner';
|
|
|
19
19
|
import { ApolloGateway } from '..';
|
|
20
20
|
import { ApolloServerBase as ApolloServer } from 'apollo-server-core';
|
|
21
21
|
import { getFederatedTestingSchema } from './execution-utils';
|
|
22
|
-
import { Schema, Operation, parseOperation, buildSchemaFromAST } from '@apollo/federation-internals';
|
|
22
|
+
import { Schema, Operation, parseOperation, buildSchemaFromAST, arrayEquals } from '@apollo/federation-internals';
|
|
23
23
|
import { addResolversToSchema, GraphQLResolverMap } from '../schema-helper';
|
|
24
24
|
|
|
25
25
|
expect.addSnapshotSerializer(astSerializer);
|
|
@@ -2736,4 +2736,259 @@ describe('executeQueryPlan', () => {
|
|
|
2736
2736
|
expect(response.errors?.map((e) => e.message)).toStrictEqual(['String cannot represent value: ["invalid"]']);
|
|
2737
2737
|
});
|
|
2738
2738
|
});
|
|
2739
|
+
|
|
2740
|
+
describe('@key', () => {
|
|
2741
|
+
test('Works on a list of scalar', async () => {
|
|
2742
|
+
const s1_data = [
|
|
2743
|
+
{ id: [0, 1], f1: "foo" },
|
|
2744
|
+
{ id: [2, 3], f1: "bar" },
|
|
2745
|
+
{ id: [4, 5], f1: "baz" },
|
|
2746
|
+
];
|
|
2747
|
+
|
|
2748
|
+
const s1 = {
|
|
2749
|
+
name: 'S1',
|
|
2750
|
+
typeDefs: gql`
|
|
2751
|
+
type T1 @key(fields: "id") {
|
|
2752
|
+
id: [Int]
|
|
2753
|
+
f1: String
|
|
2754
|
+
}
|
|
2755
|
+
`,
|
|
2756
|
+
resolvers: {
|
|
2757
|
+
T1: {
|
|
2758
|
+
__resolveReference(ref: { id: number[] }) {
|
|
2759
|
+
return s1_data.find((e) => arrayEquals(e.id, ref.id));
|
|
2760
|
+
},
|
|
2761
|
+
},
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2764
|
+
|
|
2765
|
+
const s2 = {
|
|
2766
|
+
name: 'S2',
|
|
2767
|
+
typeDefs: gql`
|
|
2768
|
+
type Query {
|
|
2769
|
+
getT1s: [T1]
|
|
2770
|
+
}
|
|
2771
|
+
|
|
2772
|
+
type T1 {
|
|
2773
|
+
id: [Int]
|
|
2774
|
+
}
|
|
2775
|
+
`,
|
|
2776
|
+
resolvers: {
|
|
2777
|
+
Query: {
|
|
2778
|
+
getT1s() {
|
|
2779
|
+
return [{id: [2, 3]}, {id: [4, 5]}];
|
|
2780
|
+
},
|
|
2781
|
+
},
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
|
|
2785
|
+
const { serviceMap, schema, queryPlanner} = getFederatedTestingSchema([ s1, s2 ]);
|
|
2786
|
+
|
|
2787
|
+
const operation = parseOp(`
|
|
2788
|
+
query {
|
|
2789
|
+
getT1s {
|
|
2790
|
+
id
|
|
2791
|
+
f1
|
|
2792
|
+
}
|
|
2793
|
+
}
|
|
2794
|
+
`, schema);
|
|
2795
|
+
const queryPlan = buildPlan(operation, queryPlanner);
|
|
2796
|
+
expect(queryPlan).toMatchInlineSnapshot(`
|
|
2797
|
+
QueryPlan {
|
|
2798
|
+
Sequence {
|
|
2799
|
+
Fetch(service: "S2") {
|
|
2800
|
+
{
|
|
2801
|
+
getT1s {
|
|
2802
|
+
__typename
|
|
2803
|
+
id
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
},
|
|
2807
|
+
Flatten(path: "getT1s.@") {
|
|
2808
|
+
Fetch(service: "S1") {
|
|
2809
|
+
{
|
|
2810
|
+
... on T1 {
|
|
2811
|
+
__typename
|
|
2812
|
+
id
|
|
2813
|
+
}
|
|
2814
|
+
} =>
|
|
2815
|
+
{
|
|
2816
|
+
... on T1 {
|
|
2817
|
+
f1
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2820
|
+
},
|
|
2821
|
+
},
|
|
2822
|
+
},
|
|
2823
|
+
}
|
|
2824
|
+
`);
|
|
2825
|
+
|
|
2826
|
+
const response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
|
|
2827
|
+
// `null` should bubble up since `f2` is now non-nullable. But we should still get the `id: 0` response.
|
|
2828
|
+
expect(response.data).toMatchInlineSnapshot(`
|
|
2829
|
+
Object {
|
|
2830
|
+
"getT1s": Array [
|
|
2831
|
+
Object {
|
|
2832
|
+
"f1": "bar",
|
|
2833
|
+
"id": Array [
|
|
2834
|
+
2,
|
|
2835
|
+
3,
|
|
2836
|
+
],
|
|
2837
|
+
},
|
|
2838
|
+
Object {
|
|
2839
|
+
"f1": "baz",
|
|
2840
|
+
"id": Array [
|
|
2841
|
+
4,
|
|
2842
|
+
5,
|
|
2843
|
+
],
|
|
2844
|
+
},
|
|
2845
|
+
],
|
|
2846
|
+
}
|
|
2847
|
+
`);
|
|
2848
|
+
});
|
|
2849
|
+
|
|
2850
|
+
test('Works on a list of objects', async () => {
|
|
2851
|
+
const s1_data = [
|
|
2852
|
+
{ o: [{a: 0, b: "b0", c: "zero"}, {a: 1, b: "b1", c: "one"}], f1: "foo" },
|
|
2853
|
+
{ o: [{a: 2, b: "b2", c: "two"}], f1: "bar" },
|
|
2854
|
+
{ o: [{a: 3, b: "b3", c: "three"}, {a: 4, b: "b4", c: "four"}], f1: "baz" },
|
|
2855
|
+
];
|
|
2856
|
+
|
|
2857
|
+
const s1 = {
|
|
2858
|
+
name: 'S1',
|
|
2859
|
+
typeDefs: gql`
|
|
2860
|
+
type T1 @key(fields: "o { a c }") {
|
|
2861
|
+
o: [O]
|
|
2862
|
+
f1: String
|
|
2863
|
+
}
|
|
2864
|
+
|
|
2865
|
+
type O {
|
|
2866
|
+
a: Int
|
|
2867
|
+
b: String
|
|
2868
|
+
c: String
|
|
2869
|
+
}
|
|
2870
|
+
`,
|
|
2871
|
+
resolvers: {
|
|
2872
|
+
T1: {
|
|
2873
|
+
__resolveReference(ref: { o: {a : number, c: string}[] }) {
|
|
2874
|
+
return s1_data.find((e) => arrayEquals(e.o, ref.o, (x, y) => x.a === y.a && x.c === y.c));
|
|
2875
|
+
},
|
|
2876
|
+
},
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
const s2 = {
|
|
2881
|
+
name: 'S2',
|
|
2882
|
+
typeDefs: gql`
|
|
2883
|
+
type Query {
|
|
2884
|
+
getT1s: [T1]
|
|
2885
|
+
}
|
|
2886
|
+
|
|
2887
|
+
type T1 {
|
|
2888
|
+
o: [O]
|
|
2889
|
+
}
|
|
2890
|
+
|
|
2891
|
+
type O {
|
|
2892
|
+
a: Int
|
|
2893
|
+
b: String
|
|
2894
|
+
c: String
|
|
2895
|
+
}
|
|
2896
|
+
`,
|
|
2897
|
+
resolvers: {
|
|
2898
|
+
Query: {
|
|
2899
|
+
getT1s() {
|
|
2900
|
+
return [{o: [{a: 2, b: "b2", c: "two"}]}, {o: [{a: 3, b: "b3", c: "three"}, {a: 4, b: "b4", c: "four"}]}];
|
|
2901
|
+
},
|
|
2902
|
+
},
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
|
|
2906
|
+
const { serviceMap, schema, queryPlanner} = getFederatedTestingSchema([ s1, s2 ]);
|
|
2907
|
+
|
|
2908
|
+
const operation = parseOp(`
|
|
2909
|
+
query {
|
|
2910
|
+
getT1s {
|
|
2911
|
+
o {
|
|
2912
|
+
a
|
|
2913
|
+
b
|
|
2914
|
+
c
|
|
2915
|
+
}
|
|
2916
|
+
f1
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
`, schema);
|
|
2920
|
+
const queryPlan = buildPlan(operation, queryPlanner);
|
|
2921
|
+
expect(queryPlan).toMatchInlineSnapshot(`
|
|
2922
|
+
QueryPlan {
|
|
2923
|
+
Sequence {
|
|
2924
|
+
Fetch(service: "S2") {
|
|
2925
|
+
{
|
|
2926
|
+
getT1s {
|
|
2927
|
+
__typename
|
|
2928
|
+
o {
|
|
2929
|
+
a
|
|
2930
|
+
c
|
|
2931
|
+
b
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
2935
|
+
},
|
|
2936
|
+
Flatten(path: "getT1s.@") {
|
|
2937
|
+
Fetch(service: "S1") {
|
|
2938
|
+
{
|
|
2939
|
+
... on T1 {
|
|
2940
|
+
__typename
|
|
2941
|
+
o {
|
|
2942
|
+
a
|
|
2943
|
+
c
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
} =>
|
|
2947
|
+
{
|
|
2948
|
+
... on T1 {
|
|
2949
|
+
f1
|
|
2950
|
+
}
|
|
2951
|
+
}
|
|
2952
|
+
},
|
|
2953
|
+
},
|
|
2954
|
+
},
|
|
2955
|
+
}
|
|
2956
|
+
`);
|
|
2957
|
+
|
|
2958
|
+
const response = await executePlan(queryPlan, operation, undefined, schema, serviceMap);
|
|
2959
|
+
// `null` should bubble up since `f2` is now non-nullable. But we should still get the `id: 0` response.
|
|
2960
|
+
expect(response.data).toMatchInlineSnapshot(`
|
|
2961
|
+
Object {
|
|
2962
|
+
"getT1s": Array [
|
|
2963
|
+
Object {
|
|
2964
|
+
"f1": "bar",
|
|
2965
|
+
"o": Array [
|
|
2966
|
+
Object {
|
|
2967
|
+
"a": 2,
|
|
2968
|
+
"b": "b2",
|
|
2969
|
+
"c": "two",
|
|
2970
|
+
},
|
|
2971
|
+
],
|
|
2972
|
+
},
|
|
2973
|
+
Object {
|
|
2974
|
+
"f1": "baz",
|
|
2975
|
+
"o": Array [
|
|
2976
|
+
Object {
|
|
2977
|
+
"a": 3,
|
|
2978
|
+
"b": "b3",
|
|
2979
|
+
"c": "three",
|
|
2980
|
+
},
|
|
2981
|
+
Object {
|
|
2982
|
+
"a": 4,
|
|
2983
|
+
"b": "b4",
|
|
2984
|
+
"c": "four",
|
|
2985
|
+
},
|
|
2986
|
+
],
|
|
2987
|
+
},
|
|
2988
|
+
],
|
|
2989
|
+
}
|
|
2990
|
+
`);
|
|
2991
|
+
});
|
|
2992
|
+
});
|
|
2993
|
+
|
|
2739
2994
|
});
|
|
@@ -18,6 +18,8 @@ import {
|
|
|
18
18
|
} from 'apollo-federation-integration-testsuite';
|
|
19
19
|
import { Logger } from 'apollo-server-types';
|
|
20
20
|
import resolvable from '@josephg/resolvable';
|
|
21
|
+
import { createHash } from '../../utilities/createHash';
|
|
22
|
+
import { getTestingSupergraphSdl } from '../execution-utils';
|
|
21
23
|
|
|
22
24
|
// The order of this was specified to preserve existing test coverage. Typically
|
|
23
25
|
// we would just import and use the `fixtures` array.
|
|
@@ -135,13 +137,17 @@ describe('lifecycle hooks', () => {
|
|
|
135
137
|
|
|
136
138
|
const [firstCall, secondCall] = mockDidUpdate.mock.calls;
|
|
137
139
|
|
|
138
|
-
|
|
140
|
+
// Note that we've composing our usual test fixtures here
|
|
141
|
+
const expectedFirstId = createHash('sha256').update(getTestingSupergraphSdl()).digest('hex');
|
|
139
142
|
expect(firstCall[0]!.compositionId).toEqual(expectedFirstId);
|
|
140
143
|
// first call should have no second "previous" argument
|
|
141
144
|
expect(firstCall[1]).toBeUndefined();
|
|
142
145
|
|
|
146
|
+
// Note that this assertion is a tad fragile in that every time we modify
|
|
147
|
+
// the supergraph (even just formatting differences), this ID will change
|
|
148
|
+
// and this test will have to updated.
|
|
143
149
|
expect(secondCall[0]!.compositionId).toEqual(
|
|
144
|
-
'
|
|
150
|
+
'3ca7f295b11b070d1e1b56a698cbfabb70cb2b5912a4ff0ecae2fb91e8709838',
|
|
145
151
|
);
|
|
146
152
|
// second call should have previous info in the second arg
|
|
147
153
|
expect(secondCall[1]!.compositionId).toEqual(expectedFirstId);
|
|
@@ -53,6 +53,8 @@ afterEach(async () => {
|
|
|
53
53
|
}
|
|
54
54
|
});
|
|
55
55
|
|
|
56
|
+
const testingFixturesDefaultCompositionId = createHash('sha256').update(getTestingSupergraphSdl()).digest('hex');
|
|
57
|
+
|
|
56
58
|
describe('Using supergraphSdl static configuration', () => {
|
|
57
59
|
it('successfully starts and serves requests to the proper services', async () => {
|
|
58
60
|
const server = await getSupergraphSdlGatewayServer();
|
|
@@ -187,7 +189,7 @@ describe('Using supergraphSdl dynamic configuration', () => {
|
|
|
187
189
|
const { state, compositionId } = gateway.__testing();
|
|
188
190
|
expect(state.phase).toEqual('loaded');
|
|
189
191
|
expect(compositionId).toEqual(
|
|
190
|
-
|
|
192
|
+
testingFixturesDefaultCompositionId,
|
|
191
193
|
);
|
|
192
194
|
|
|
193
195
|
await gateway.stop();
|
|
@@ -212,7 +214,7 @@ describe('Using supergraphSdl dynamic configuration', () => {
|
|
|
212
214
|
const { state, compositionId } = gateway.__testing();
|
|
213
215
|
expect(state.phase).toEqual('loaded');
|
|
214
216
|
expect(compositionId).toEqual(
|
|
215
|
-
|
|
217
|
+
testingFixturesDefaultCompositionId,
|
|
216
218
|
);
|
|
217
219
|
|
|
218
220
|
await expect(healthCheckCallback!(supergraphSdl)).resolves.toBeUndefined();
|
|
@@ -294,7 +296,7 @@ describe('Using supergraphSdl dynamic configuration', () => {
|
|
|
294
296
|
const { state, compositionId } = gateway.__testing();
|
|
295
297
|
expect(state.phase).toEqual('loaded');
|
|
296
298
|
expect(compositionId).toEqual(
|
|
297
|
-
|
|
299
|
+
testingFixturesDefaultCompositionId
|
|
298
300
|
);
|
|
299
301
|
|
|
300
302
|
await expect(healthCheckCallback!(supergraphSdl)).rejects.toThrowError(
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import gql from 'graphql-tag';
|
|
2
1
|
import { execute } from '../execution-utils';
|
|
3
2
|
|
|
4
|
-
import { astSerializer, queryPlanSerializer } from 'apollo-federation-integration-testsuite';
|
|
3
|
+
import { astSerializer, fed2gql as gql, queryPlanSerializer } from 'apollo-federation-integration-testsuite';
|
|
5
4
|
|
|
6
5
|
expect.addSnapshotSerializer(astSerializer);
|
|
7
6
|
expect.addSnapshotSerializer(queryPlanSerializer);
|
|
@@ -849,7 +848,7 @@ describe("doesn't result in duplicate fetches", () => {
|
|
|
849
848
|
type User @key(fields: "id") {
|
|
850
849
|
id: ID!
|
|
851
850
|
name: String
|
|
852
|
-
username: String
|
|
851
|
+
username: String @shareable
|
|
853
852
|
}
|
|
854
853
|
`,
|
|
855
854
|
},
|
|
@@ -1085,7 +1084,7 @@ it("when including the same nested fields under different type conditions", asyn
|
|
|
1085
1084
|
type User @key(fields: "id") {
|
|
1086
1085
|
id: ID!
|
|
1087
1086
|
name: String
|
|
1088
|
-
username: String
|
|
1087
|
+
username: String @shareable
|
|
1089
1088
|
}
|
|
1090
1089
|
`,
|
|
1091
1090
|
},
|
|
@@ -1293,7 +1292,7 @@ it('when including multiple nested fields to the same service under different ty
|
|
|
1293
1292
|
type User @key(fields: "id") {
|
|
1294
1293
|
id: ID!
|
|
1295
1294
|
name: String
|
|
1296
|
-
username: String
|
|
1295
|
+
username: String @shareable
|
|
1297
1296
|
}
|
|
1298
1297
|
`,
|
|
1299
1298
|
},
|
|
@@ -1514,7 +1513,7 @@ it('when exploding types through multiple levels', async () => {
|
|
|
1514
1513
|
type User @key(fields: "id") {
|
|
1515
1514
|
id: ID!
|
|
1516
1515
|
name: String
|
|
1517
|
-
username: String
|
|
1516
|
+
username: String @shareable
|
|
1518
1517
|
}
|
|
1519
1518
|
`,
|
|
1520
1519
|
},
|
|
@@ -1700,7 +1699,7 @@ it("when including the same nested fields under different type conditions that a
|
|
|
1700
1699
|
type User @key(fields: "id") {
|
|
1701
1700
|
id: ID!
|
|
1702
1701
|
name: String
|
|
1703
|
-
username: String
|
|
1702
|
+
username: String @shareable
|
|
1704
1703
|
}
|
|
1705
1704
|
`,
|
|
1706
1705
|
},
|
|
@@ -121,9 +121,10 @@ export function mockSupergraphSdlRequestSuccessIfAfter(
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
export function mockSupergraphSdlRequestIfAfterUnchanged(
|
|
124
|
-
|
|
124
|
+
ifAfter: string | null = null,
|
|
125
|
+
url: string = mockCloudConfigUrl1,
|
|
125
126
|
) {
|
|
126
|
-
return mockSupergraphSdlRequestIfAfter(ifAfter).reply(
|
|
127
|
+
return mockSupergraphSdlRequestIfAfter(ifAfter, url).reply(
|
|
127
128
|
200,
|
|
128
129
|
JSON.stringify({
|
|
129
130
|
data: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import gql from 'graphql-tag';
|
|
2
1
|
import { execute } from '../execution-utils';
|
|
3
2
|
import {
|
|
4
3
|
astSerializer,
|
|
4
|
+
fed2gql as gql,
|
|
5
5
|
queryPlanSerializer,
|
|
6
6
|
} from 'apollo-federation-integration-testsuite';
|
|
7
7
|
|
|
@@ -200,7 +200,7 @@ describe('value types', () => {
|
|
|
200
200
|
valueType: ValueType
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
type ValueType {
|
|
203
|
+
type ValueType @shareable {
|
|
204
204
|
id: ID!
|
|
205
205
|
user: User! @provides(fields: "name")
|
|
206
206
|
}
|
|
@@ -226,7 +226,7 @@ describe('value types', () => {
|
|
|
226
226
|
otherValueType: ValueType
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
-
type ValueType {
|
|
229
|
+
type ValueType @shareable {
|
|
230
230
|
id: ID!
|
|
231
231
|
user: User! @provides(fields: "name")
|
|
232
232
|
}
|
|
@@ -250,7 +250,7 @@ describe('value types', () => {
|
|
|
250
250
|
typeDefs: gql`
|
|
251
251
|
type User @key(fields: "id") {
|
|
252
252
|
id: ID!
|
|
253
|
-
name: String!
|
|
253
|
+
name: String! @shareable
|
|
254
254
|
address: String!
|
|
255
255
|
}
|
|
256
256
|
`,
|
package/src/executeQueryPlan.ts
CHANGED
|
@@ -298,6 +298,7 @@ async function executeFetch<TContext>(
|
|
|
298
298
|
context,
|
|
299
299
|
fetch.operation,
|
|
300
300
|
variables,
|
|
301
|
+
fetch.operationName
|
|
301
302
|
);
|
|
302
303
|
|
|
303
304
|
for (const entity of entities) {
|
|
@@ -333,6 +334,7 @@ async function executeFetch<TContext>(
|
|
|
333
334
|
context,
|
|
334
335
|
fetch.operation,
|
|
335
336
|
{...variables, representations},
|
|
337
|
+
fetch.operationName
|
|
336
338
|
);
|
|
337
339
|
|
|
338
340
|
if (!dataReceivedFromService) {
|
|
@@ -374,6 +376,7 @@ async function executeFetch<TContext>(
|
|
|
374
376
|
context: ExecutionContext<TContext>,
|
|
375
377
|
source: string,
|
|
376
378
|
variables: Record<string, any>,
|
|
379
|
+
operationName: string | undefined
|
|
377
380
|
): Promise<ResultMap | void | null> {
|
|
378
381
|
// We declare this as 'any' because it is missing url and method, which
|
|
379
382
|
// GraphQLRequest.http is supposed to have if it exists.
|
|
@@ -402,6 +405,7 @@ async function executeFetch<TContext>(
|
|
|
402
405
|
request: {
|
|
403
406
|
query: source,
|
|
404
407
|
variables,
|
|
408
|
+
operationName,
|
|
405
409
|
http,
|
|
406
410
|
},
|
|
407
411
|
incomingRequestContext: context.requestContext,
|
package/src/index.ts
CHANGED
|
@@ -402,7 +402,7 @@ export class ApolloGateway implements GraphQLService {
|
|
|
402
402
|
apiKey: this.apolloConfig!.key!,
|
|
403
403
|
uplinkEndpoints,
|
|
404
404
|
maxRetries:
|
|
405
|
-
this.config.uplinkMaxRetries ?? uplinkEndpoints.length * 3,
|
|
405
|
+
this.config.uplinkMaxRetries ?? uplinkEndpoints.length * 3 - 1, // -1 for the initial request
|
|
406
406
|
subgraphHealthCheck: this.config.serviceHealthCheck,
|
|
407
407
|
fetcher: this.fetcher,
|
|
408
408
|
logger: this.logger,
|
|
@@ -1127,3 +1127,6 @@ export {
|
|
|
1127
1127
|
SupergraphSdlHook,
|
|
1128
1128
|
SupergraphManager
|
|
1129
1129
|
} from './config';
|
|
1130
|
+
|
|
1131
|
+
export { UplinkFetcherError } from "./supergraphManagers"
|
|
1132
|
+
|
|
@@ -219,7 +219,7 @@ export class LegacyFetcher implements SupergraphManager {
|
|
|
219
219
|
|
|
220
220
|
private logUpdateFailure(e: any) {
|
|
221
221
|
this.config.logger?.error(
|
|
222
|
-
'
|
|
222
|
+
'LegacyFetcher failed to update supergraph with the following error: ' +
|
|
223
223
|
(e.message ?? e),
|
|
224
224
|
);
|
|
225
225
|
}
|
|
@@ -72,7 +72,7 @@ export class LocalCompose implements SupergraphManager {
|
|
|
72
72
|
|
|
73
73
|
private logUpdateFailure(e: any) {
|
|
74
74
|
this.config.logger?.error(
|
|
75
|
-
'
|
|
75
|
+
'LocalCompose failed to update supergraph with the following error: ' +
|
|
76
76
|
(e.message ?? e),
|
|
77
77
|
);
|
|
78
78
|
}
|