@apollo/gateway 2.1.0-alpha.0 → 2.1.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.d.ts +5 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/datasources/LocalGraphQLDataSource.d.ts +2 -2
- package/dist/datasources/LocalGraphQLDataSource.d.ts.map +1 -1
- package/dist/datasources/LocalGraphQLDataSource.js +0 -2
- package/dist/datasources/LocalGraphQLDataSource.js.map +1 -1
- package/dist/datasources/RemoteGraphQLDataSource.d.ts +6 -6
- package/dist/datasources/RemoteGraphQLDataSource.d.ts.map +1 -1
- package/dist/datasources/RemoteGraphQLDataSource.js +15 -20
- package/dist/datasources/RemoteGraphQLDataSource.js.map +1 -1
- package/dist/datasources/types.d.ts +6 -5
- package/dist/datasources/types.d.ts.map +1 -1
- package/dist/executeQueryPlan.d.ts +3 -3
- package/dist/executeQueryPlan.d.ts.map +1 -1
- package/dist/executeQueryPlan.js +30 -16
- package/dist/executeQueryPlan.js.map +1 -1
- package/dist/index.d.ts +9 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -30
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +1 -1
- package/dist/logger.js.map +1 -1
- package/dist/operationContext.d.ts.map +1 -1
- package/dist/operationContext.js +3 -7
- package/dist/operationContext.js.map +1 -1
- package/dist/supergraphManagers/IntrospectAndCompose/index.d.ts +1 -1
- package/dist/supergraphManagers/IntrospectAndCompose/index.d.ts.map +1 -1
- package/dist/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.d.ts +1 -1
- package/dist/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.d.ts.map +1 -1
- package/dist/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.js.map +1 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/index.d.ts +9 -7
- package/dist/supergraphManagers/UplinkSupergraphManager/index.d.ts.map +1 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/index.js +38 -41
- package/dist/supergraphManagers/UplinkSupergraphManager/index.js.map +1 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/loadSupergraphSdlFromStorage.d.ts +9 -8
- package/dist/supergraphManagers/UplinkSupergraphManager/loadSupergraphSdlFromStorage.d.ts.map +1 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/loadSupergraphSdlFromStorage.js +19 -10
- package/dist/supergraphManagers/UplinkSupergraphManager/loadSupergraphSdlFromStorage.js.map +1 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/outOfBandReporter.d.ts +2 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/outOfBandReporter.d.ts.map +1 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/outOfBandReporter.js.map +1 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/types.d.ts +9 -0
- package/dist/supergraphManagers/UplinkSupergraphManager/types.d.ts.map +1 -0
- package/dist/supergraphManagers/UplinkSupergraphManager/types.js +5 -0
- package/dist/supergraphManagers/UplinkSupergraphManager/types.js.map +1 -0
- package/package.json +9 -11
- package/src/__tests__/buildQueryPlan.test.ts +6 -2
- package/src/__tests__/executeQueryPlan.test.ts +208 -8
- package/src/__tests__/execution-utils.ts +8 -6
- package/src/__tests__/gateway/executor.test.ts +2 -2
- package/src/__tests__/gateway/lifecycle-hooks.test.ts +1 -1
- package/src/__tests__/integration/abstract-types.test.ts +39 -71
- package/src/__tests__/integration/configuration.test.ts +2 -2
- package/src/__tests__/integration/managed.test.ts +72 -44
- package/src/__tests__/integration/networkRequests.test.ts +10 -23
- package/src/config.ts +6 -6
- package/src/datasources/LocalGraphQLDataSource.ts +2 -4
- package/src/datasources/RemoteGraphQLDataSource.ts +28 -44
- package/src/datasources/__tests__/LocalGraphQLDataSource.test.ts +2 -2
- package/src/datasources/__tests__/RemoteGraphQLDataSource.test.ts +14 -19
- package/src/datasources/types.ts +9 -5
- package/src/executeQueryPlan.ts +59 -45
- package/src/index.ts +31 -65
- package/src/logger.ts +1 -1
- package/src/operationContext.ts +5 -7
- package/src/supergraphManagers/IntrospectAndCompose/index.ts +1 -1
- package/src/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.ts +3 -3
- package/src/supergraphManagers/UplinkSupergraphManager/__tests__/UplinkSupergraphManager.test.ts +1 -3
- package/src/supergraphManagers/UplinkSupergraphManager/__tests__/loadSupergraphSdlFromStorage.test.ts +51 -16
- package/src/supergraphManagers/UplinkSupergraphManager/index.ts +67 -57
- package/src/supergraphManagers/UplinkSupergraphManager/loadSupergraphSdlFromStorage.ts +31 -19
- package/src/supergraphManagers/UplinkSupergraphManager/outOfBandReporter.ts +2 -1
- package/src/supergraphManagers/UplinkSupergraphManager/types.ts +10 -0
|
@@ -49,7 +49,7 @@ describe('ApolloGateway executor', () => {
|
|
|
49
49
|
variables: { first: '3' },
|
|
50
50
|
},
|
|
51
51
|
queryHash: 'hashed',
|
|
52
|
-
context:
|
|
52
|
+
context: {},
|
|
53
53
|
cache: {} as any,
|
|
54
54
|
logger,
|
|
55
55
|
});
|
|
@@ -85,7 +85,7 @@ describe('ApolloGateway executor', () => {
|
|
|
85
85
|
document: gql(source),
|
|
86
86
|
request: {},
|
|
87
87
|
queryHash: 'hashed',
|
|
88
|
-
context:
|
|
88
|
+
context: {},
|
|
89
89
|
cache: {} as any,
|
|
90
90
|
logger,
|
|
91
91
|
});
|
|
@@ -147,7 +147,7 @@ describe('lifecycle hooks', () => {
|
|
|
147
147
|
// the supergraph (even just formatting differences), this ID will change
|
|
148
148
|
// and this test will have to updated.
|
|
149
149
|
expect(secondCall[0]!.compositionId).toEqual(
|
|
150
|
-
'
|
|
150
|
+
'cc95112b64179c4e549de788b051f44010a02877f568649a42caeeee6a135601',
|
|
151
151
|
);
|
|
152
152
|
// second call should have previous info in the second arg
|
|
153
153
|
expect(secondCall[1]!.compositionId).toEqual(expectedFirstId);
|
|
@@ -1626,14 +1626,16 @@ it('when exploding types through multiple levels', async () => {
|
|
|
1626
1626
|
} =>
|
|
1627
1627
|
{
|
|
1628
1628
|
... on Book {
|
|
1629
|
-
|
|
1630
|
-
body
|
|
1631
|
-
}
|
|
1629
|
+
...ProductReviews
|
|
1632
1630
|
}
|
|
1633
1631
|
... on Furniture {
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1632
|
+
...ProductReviews
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
fragment ProductReviews on Product {
|
|
1637
|
+
reviews {
|
|
1638
|
+
body
|
|
1637
1639
|
}
|
|
1638
1640
|
}
|
|
1639
1641
|
},
|
|
@@ -1643,23 +1645,6 @@ it('when exploding types through multiple levels', async () => {
|
|
|
1643
1645
|
`);
|
|
1644
1646
|
});
|
|
1645
1647
|
|
|
1646
|
-
// This test case describes a situation that isn't fixed by the deduplication
|
|
1647
|
-
// workaround. It is here to remind us to look into this, but it doesn't
|
|
1648
|
-
// actually test for the failing behavior so the test still succeeds.
|
|
1649
|
-
//
|
|
1650
|
-
// In cases where different possible types live in different
|
|
1651
|
-
// services, you can't just merge the dependent fetches because they don't
|
|
1652
|
-
// have the same parent. What you want here is to have these dependent fetches
|
|
1653
|
-
// execute separately, but only take the objects fetched by its parent as input.
|
|
1654
|
-
// The problem currently is that these fetches act on on the same path, so
|
|
1655
|
-
// depending on the timing either one (or both) will end up fetching the same
|
|
1656
|
-
// data just fetched by the other.
|
|
1657
|
-
//
|
|
1658
|
-
// To make this more concrete, in this case that means we'll fetch all of the
|
|
1659
|
-
// reviews and authors twice.
|
|
1660
|
-
//
|
|
1661
|
-
// Solving this requires us to filter on the types of response objects as
|
|
1662
|
-
// opposed to just collecting all objects in the path.
|
|
1663
1648
|
it("when including the same nested fields under different type conditions that are split between services", async () => {
|
|
1664
1649
|
const query = `#graphql
|
|
1665
1650
|
query {
|
|
@@ -1829,63 +1814,46 @@ it("when including the same nested fields under different type conditions that a
|
|
|
1829
1814
|
}
|
|
1830
1815
|
},
|
|
1831
1816
|
},
|
|
1832
|
-
Flatten(path: "topProducts.@.reviews.@.author") {
|
|
1833
|
-
Fetch(service: "accounts") {
|
|
1834
|
-
{
|
|
1835
|
-
... on User {
|
|
1836
|
-
__typename
|
|
1837
|
-
id
|
|
1838
|
-
}
|
|
1839
|
-
} =>
|
|
1840
|
-
{
|
|
1841
|
-
... on User {
|
|
1842
|
-
name
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
1845
|
-
},
|
|
1846
|
-
},
|
|
1847
1817
|
},
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
{
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
{
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
__typename
|
|
1862
|
-
id
|
|
1863
|
-
username
|
|
1864
|
-
}
|
|
1865
|
-
body
|
|
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
|
|
1866
1831
|
id
|
|
1832
|
+
username
|
|
1867
1833
|
}
|
|
1868
|
-
|
|
1869
|
-
}
|
|
1870
|
-
},
|
|
1871
|
-
},
|
|
1872
|
-
Flatten(path: "topProducts.@.reviews.@.author") {
|
|
1873
|
-
Fetch(service: "accounts") {
|
|
1874
|
-
{
|
|
1875
|
-
... on User {
|
|
1876
|
-
__typename
|
|
1834
|
+
body
|
|
1877
1835
|
id
|
|
1878
1836
|
}
|
|
1879
|
-
} =>
|
|
1880
|
-
{
|
|
1881
|
-
... on User {
|
|
1882
|
-
name
|
|
1883
|
-
}
|
|
1884
1837
|
}
|
|
1885
|
-
}
|
|
1838
|
+
}
|
|
1886
1839
|
},
|
|
1887
1840
|
},
|
|
1888
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
|
+
},
|
|
1889
1857
|
},
|
|
1890
1858
|
}
|
|
1891
1859
|
`);
|
|
@@ -202,8 +202,8 @@ describe('gateway startup errors', () => {
|
|
|
202
202
|
|
|
203
203
|
const expected =
|
|
204
204
|
"A valid schema couldn't be composed. The following composition errors were found:\n"
|
|
205
|
-
+ ' [accounts] On type "User", for @key(fields: "id"): Cannot query field "id" on type "User" (the field should
|
|
206
|
-
+ ' [accounts] On type "Account", for @key(fields: "id"): Cannot query field "id" on type "Account" (the field should
|
|
205
|
+
+ ' [accounts] On type "User", for @key(fields: "id"): Cannot query field "id" on type "User" (the field should either be added to this subgraph or, if it should not be resolved by this subgraph, you need to add it to this subgraph with @external).\n'
|
|
206
|
+
+ ' [accounts] On type "Account", for @key(fields: "id"): Cannot query field "id" on type "Account" (the field should either be added to this subgraph or, if it should not be resolved by this subgraph, you need to add it to this subgraph with @external).'
|
|
207
207
|
expect(err.message).toBe(expected);
|
|
208
208
|
});
|
|
209
209
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import mockedEnv from 'mocked-env';
|
|
2
|
+
import fetcher from 'make-fetch-happen';
|
|
2
3
|
|
|
3
4
|
import { ApolloGateway, UplinkSupergraphManager } from '@apollo/gateway';
|
|
4
5
|
import { ApolloServer } from 'apollo-server';
|
|
@@ -22,8 +23,6 @@ beforeEach(() => {
|
|
|
22
23
|
});
|
|
23
24
|
|
|
24
25
|
afterEach(async () => {
|
|
25
|
-
nockAfterEach();
|
|
26
|
-
|
|
27
26
|
if (server) {
|
|
28
27
|
await server.stop();
|
|
29
28
|
server = undefined;
|
|
@@ -34,6 +33,8 @@ afterEach(async () => {
|
|
|
34
33
|
gateway = undefined;
|
|
35
34
|
}
|
|
36
35
|
|
|
36
|
+
nockAfterEach();
|
|
37
|
+
|
|
37
38
|
if (cleanUp) {
|
|
38
39
|
cleanUp();
|
|
39
40
|
cleanUp = undefined;
|
|
@@ -105,6 +106,30 @@ describe('minimal gateway', () => {
|
|
|
105
106
|
schemaConfigDeliveryEndpoint,
|
|
106
107
|
]);
|
|
107
108
|
});
|
|
109
|
+
|
|
110
|
+
it('supports a custom fetcher', async () => {
|
|
111
|
+
cleanUp = mockedEnv({
|
|
112
|
+
APOLLO_KEY: apiKey,
|
|
113
|
+
APOLLO_GRAPH_REF: graphRef,
|
|
114
|
+
});
|
|
115
|
+
mockSupergraphSdlRequestSuccess({ url: /.*?apollographql.com/ });
|
|
116
|
+
|
|
117
|
+
let calls = 0;
|
|
118
|
+
gateway = new ApolloGateway({
|
|
119
|
+
logger,
|
|
120
|
+
fetcher: (...args) => {
|
|
121
|
+
calls++;
|
|
122
|
+
return fetcher(...args);
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
server = new ApolloServer({
|
|
126
|
+
gateway,
|
|
127
|
+
plugins: [ApolloServerPluginUsageReportingDisabled()],
|
|
128
|
+
});
|
|
129
|
+
await server.listen({ port: 0 });
|
|
130
|
+
|
|
131
|
+
expect(calls).toEqual(1);
|
|
132
|
+
});
|
|
108
133
|
});
|
|
109
134
|
|
|
110
135
|
describe('Managed gateway with explicit UplinkSupergraphManager', () => {
|
|
@@ -134,7 +159,6 @@ describe('Managed gateway with explicit UplinkSupergraphManager', () => {
|
|
|
134
159
|
graphRef,
|
|
135
160
|
logger,
|
|
136
161
|
maxRetries: 0,
|
|
137
|
-
fallbackPollIntervalInMs: 0,
|
|
138
162
|
async onFailureToFetchSupergraphSdlDuringInit() {
|
|
139
163
|
hasFired = true;
|
|
140
164
|
return supergraphSchema;
|
|
@@ -155,25 +179,27 @@ describe('Managed gateway with explicit UplinkSupergraphManager', () => {
|
|
|
155
179
|
|
|
156
180
|
const supergraphSchema = getTestingSupergraphSdl();
|
|
157
181
|
let hasFired;
|
|
182
|
+
let uplinkManager = new UplinkSupergraphManager({
|
|
183
|
+
apiKey,
|
|
184
|
+
graphRef,
|
|
185
|
+
logger,
|
|
186
|
+
maxRetries: 0,
|
|
187
|
+
async onFailureToFetchSupergraphSdlAfterInit() {
|
|
188
|
+
hasFired = true;
|
|
189
|
+
return supergraphSchema;
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
// Set pollIntervalMs lower than the typically allowed value so we don't wait 10s between polling
|
|
193
|
+
uplinkManager['pollIntervalMs'] = 0;
|
|
194
|
+
|
|
158
195
|
gateway = new ApolloGateway({
|
|
159
196
|
logger,
|
|
160
|
-
supergraphSdl:
|
|
161
|
-
apiKey,
|
|
162
|
-
graphRef,
|
|
163
|
-
logger,
|
|
164
|
-
maxRetries: 0,
|
|
165
|
-
fallbackPollIntervalInMs: 0,
|
|
166
|
-
async onFailureToFetchSupergraphSdlAfterInit() {
|
|
167
|
-
hasFired = true;
|
|
168
|
-
return supergraphSchema;
|
|
169
|
-
},
|
|
170
|
-
}),
|
|
197
|
+
supergraphSdl: uplinkManager,
|
|
171
198
|
});
|
|
172
199
|
|
|
173
200
|
await expect(gateway.load()).resolves.not.toThrow();
|
|
174
201
|
expect(hasFired).toBeFalsy();
|
|
175
202
|
|
|
176
|
-
const uplinkManager = gateway.supergraphManager as UplinkSupergraphManager;
|
|
177
203
|
await uplinkManager.nextFetch();
|
|
178
204
|
|
|
179
205
|
expect(hasFired).toBeTruthy();
|
|
@@ -181,7 +207,7 @@ describe('Managed gateway with explicit UplinkSupergraphManager', () => {
|
|
|
181
207
|
|
|
182
208
|
it.each([
|
|
183
209
|
['x', 'Syntax Error: Unexpected Name "x".'],
|
|
184
|
-
['', '
|
|
210
|
+
['', 'Invalid supergraph schema supplied during initialization.'],
|
|
185
211
|
[' ', 'Syntax Error: Unexpected <EOF>.'],
|
|
186
212
|
['type Query {hi: String}', 'Invalid supergraph: must be a core schema'],
|
|
187
213
|
])(
|
|
@@ -196,7 +222,6 @@ describe('Managed gateway with explicit UplinkSupergraphManager', () => {
|
|
|
196
222
|
graphRef,
|
|
197
223
|
logger,
|
|
198
224
|
maxRetries: 0,
|
|
199
|
-
fallbackPollIntervalInMs: 0,
|
|
200
225
|
async onFailureToFetchSupergraphSdlDuringInit() {
|
|
201
226
|
return schemaText;
|
|
202
227
|
},
|
|
@@ -220,26 +245,27 @@ describe('Managed gateway with explicit UplinkSupergraphManager', () => {
|
|
|
220
245
|
.reply(500);
|
|
221
246
|
|
|
222
247
|
let hasFired;
|
|
248
|
+
let uplinkManager = new UplinkSupergraphManager({
|
|
249
|
+
apiKey,
|
|
250
|
+
graphRef,
|
|
251
|
+
logger,
|
|
252
|
+
maxRetries: 0,
|
|
253
|
+
async onFailureToFetchSupergraphSdlAfterInit() {
|
|
254
|
+
hasFired = true;
|
|
255
|
+
return schemaText;
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
// Set pollIntervalMs lower than the typically allowed value so we don't wait 10s between polling
|
|
259
|
+
uplinkManager['pollIntervalMs'] = 0;
|
|
260
|
+
|
|
223
261
|
gateway = new ApolloGateway({
|
|
224
262
|
logger,
|
|
225
|
-
supergraphSdl:
|
|
226
|
-
apiKey,
|
|
227
|
-
graphRef,
|
|
228
|
-
logger,
|
|
229
|
-
maxRetries: 0,
|
|
230
|
-
fallbackPollIntervalInMs: 0,
|
|
231
|
-
async onFailureToFetchSupergraphSdlAfterInit() {
|
|
232
|
-
hasFired = true;
|
|
233
|
-
return schemaText;
|
|
234
|
-
},
|
|
235
|
-
}),
|
|
263
|
+
supergraphSdl: uplinkManager
|
|
236
264
|
});
|
|
237
265
|
|
|
238
266
|
await expect(gateway.load()).resolves.not.toThrow();
|
|
239
267
|
expect(hasFired).toBeFalsy();
|
|
240
268
|
|
|
241
|
-
const uplinkManager =
|
|
242
|
-
gateway.supergraphManager as UplinkSupergraphManager;
|
|
243
269
|
await uplinkManager.nextFetch();
|
|
244
270
|
|
|
245
271
|
expect(hasFired).toBeTruthy();
|
|
@@ -250,7 +276,7 @@ describe('Managed gateway with explicit UplinkSupergraphManager', () => {
|
|
|
250
276
|
);
|
|
251
277
|
|
|
252
278
|
it.each([null, ''])(
|
|
253
|
-
'uses existing supergraph schema
|
|
279
|
+
'uses existing supergraph schema if false-y value returned from callback after init: %p',
|
|
254
280
|
async (schemaText) => {
|
|
255
281
|
// This is kinda wonky to read: we're responding the first time with success, then the next fetch should fail
|
|
256
282
|
mockSupergraphSdlRequestSuccess({ url: /.*?apollographql.com/ })
|
|
@@ -258,26 +284,28 @@ describe('Managed gateway with explicit UplinkSupergraphManager', () => {
|
|
|
258
284
|
.reply(500);
|
|
259
285
|
|
|
260
286
|
let hasFired;
|
|
287
|
+
let uplinkManager = new UplinkSupergraphManager({
|
|
288
|
+
apiKey,
|
|
289
|
+
graphRef,
|
|
290
|
+
logger,
|
|
291
|
+
maxRetries: 0,
|
|
292
|
+
|
|
293
|
+
async onFailureToFetchSupergraphSdlAfterInit() {
|
|
294
|
+
hasFired = true;
|
|
295
|
+
return schemaText;
|
|
296
|
+
},
|
|
297
|
+
});
|
|
298
|
+
// Set pollIntervalMs lower than the typically allowed value so we don't wait 10s between polling
|
|
299
|
+
uplinkManager['pollIntervalMs'] = 0;
|
|
300
|
+
|
|
261
301
|
gateway = new ApolloGateway({
|
|
262
302
|
logger,
|
|
263
|
-
supergraphSdl:
|
|
264
|
-
apiKey,
|
|
265
|
-
graphRef,
|
|
266
|
-
logger,
|
|
267
|
-
maxRetries: 0,
|
|
268
|
-
fallbackPollIntervalInMs: 0,
|
|
269
|
-
async onFailureToFetchSupergraphSdlAfterInit() {
|
|
270
|
-
hasFired = true;
|
|
271
|
-
return schemaText;
|
|
272
|
-
},
|
|
273
|
-
}),
|
|
303
|
+
supergraphSdl: uplinkManager,
|
|
274
304
|
});
|
|
275
305
|
|
|
276
306
|
await expect(gateway.load()).resolves.not.toThrow();
|
|
277
307
|
expect(hasFired).toBeFalsy();
|
|
278
308
|
|
|
279
|
-
const uplinkManager =
|
|
280
|
-
gateway.supergraphManager as UplinkSupergraphManager;
|
|
281
309
|
await uplinkManager.nextFetch();
|
|
282
310
|
|
|
283
311
|
expect(hasFired).toBeTruthy();
|
|
@@ -2,7 +2,7 @@ import gql from 'graphql-tag';
|
|
|
2
2
|
import { GraphQLObjectType, GraphQLSchema } from 'graphql';
|
|
3
3
|
import mockedEnv from 'mocked-env';
|
|
4
4
|
import type { Logger } from '@apollo/utils.logger';
|
|
5
|
-
import { ApolloGateway } from '../..';
|
|
5
|
+
import { ApolloGateway, UplinkSupergraphManager } from '../..';
|
|
6
6
|
import {
|
|
7
7
|
mockSdlQuerySuccess,
|
|
8
8
|
mockServiceHealthCheckSuccess,
|
|
@@ -56,8 +56,12 @@ function getRootQueryFields(schema?: GraphQLSchema): string[] {
|
|
|
56
56
|
let logger: Logger;
|
|
57
57
|
let gateway: ApolloGateway | null = null;
|
|
58
58
|
let cleanUp: (() => void) | null = null;
|
|
59
|
+
let originalMinPollInterval = UplinkSupergraphManager.MIN_POLL_INTERVAL_MS;
|
|
59
60
|
|
|
60
61
|
beforeEach(() => {
|
|
62
|
+
// Set the min poll interval artificially low so we're not waiting during tests
|
|
63
|
+
// @ts-ignore
|
|
64
|
+
UplinkSupergraphManager['MIN_POLL_INTERVAL_MS'] = 100;
|
|
61
65
|
nockBeforeEach();
|
|
62
66
|
|
|
63
67
|
const warn = jest.fn();
|
|
@@ -74,13 +78,15 @@ beforeEach(() => {
|
|
|
74
78
|
});
|
|
75
79
|
|
|
76
80
|
afterEach(async () => {
|
|
77
|
-
|
|
78
|
-
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
UplinkSupergraphManager['MIN_POLL_INTERVAL_MS'] = originalMinPollInterval;
|
|
79
83
|
if (gateway) {
|
|
80
84
|
await gateway.stop();
|
|
81
85
|
gateway = null;
|
|
82
86
|
}
|
|
83
87
|
|
|
88
|
+
nockAfterEach();
|
|
89
|
+
|
|
84
90
|
if (cleanUp) {
|
|
85
91
|
cleanUp();
|
|
86
92
|
cleanUp = null;
|
|
@@ -90,7 +96,7 @@ afterEach(async () => {
|
|
|
90
96
|
it('Queries remote endpoints for their SDLs', async () => {
|
|
91
97
|
mockSdlQuerySuccess(simpleService);
|
|
92
98
|
|
|
93
|
-
gateway = new ApolloGateway({ serviceList: [simpleService] });
|
|
99
|
+
gateway = new ApolloGateway({ serviceList: [simpleService], logger });
|
|
94
100
|
await gateway.load();
|
|
95
101
|
expect(gateway.schema!.getType('User')!.description).toBe('This is my User');
|
|
96
102
|
});
|
|
@@ -139,8 +145,6 @@ it('Updates Supergraph SDL from remote storage', async () => {
|
|
|
139
145
|
logger,
|
|
140
146
|
uplinkEndpoints: [mockCloudConfigUrl1],
|
|
141
147
|
});
|
|
142
|
-
// for testing purposes, a short pollInterval is ideal so we'll override here
|
|
143
|
-
gateway['pollIntervalInMs'] = 100;
|
|
144
148
|
|
|
145
149
|
const schemas: GraphQLSchema[] = [];
|
|
146
150
|
gateway.onSchemaLoadOrUpdate(({ apiSchema }) => {
|
|
@@ -199,9 +203,6 @@ describe('Supergraph SDL update failures', () => {
|
|
|
199
203
|
uplinkMaxRetries: 0,
|
|
200
204
|
});
|
|
201
205
|
|
|
202
|
-
// for testing purposes, a short pollInterval is ideal so we'll override here
|
|
203
|
-
gateway['pollIntervalInMs'] = 100;
|
|
204
|
-
|
|
205
206
|
await gateway.load(mockApolloConfig);
|
|
206
207
|
await errorLoggedPromise;
|
|
207
208
|
|
|
@@ -231,8 +232,6 @@ describe('Supergraph SDL update failures', () => {
|
|
|
231
232
|
uplinkEndpoints: [mockCloudConfigUrl1],
|
|
232
233
|
uplinkMaxRetries: 0,
|
|
233
234
|
});
|
|
234
|
-
// for testing purposes, a short pollInterval is ideal so we'll override here
|
|
235
|
-
gateway['pollIntervalInMs'] = 100;
|
|
236
235
|
|
|
237
236
|
await gateway.load(mockApolloConfig);
|
|
238
237
|
await errorLoggedPromise;
|
|
@@ -265,8 +264,6 @@ describe('Supergraph SDL update failures', () => {
|
|
|
265
264
|
logger,
|
|
266
265
|
uplinkEndpoints: [mockCloudConfigUrl1],
|
|
267
266
|
});
|
|
268
|
-
// for testing purposes, a short pollInterval is ideal so we'll override here
|
|
269
|
-
gateway['pollIntervalInMs'] = 100;
|
|
270
267
|
|
|
271
268
|
await gateway.load(mockApolloConfig);
|
|
272
269
|
await errorLoggedPromise;
|
|
@@ -295,8 +292,6 @@ describe('Supergraph SDL update failures', () => {
|
|
|
295
292
|
logger,
|
|
296
293
|
uplinkEndpoints: [mockCloudConfigUrl1],
|
|
297
294
|
});
|
|
298
|
-
// for testing purposes, a short pollInterval is ideal so we'll override here
|
|
299
|
-
gateway['pollIntervalInMs'] = 100;
|
|
300
295
|
|
|
301
296
|
await expect(
|
|
302
297
|
gateway.load(mockApolloConfig),
|
|
@@ -332,8 +327,6 @@ it('Rollsback to a previous schema when triggered', async () => {
|
|
|
332
327
|
logger,
|
|
333
328
|
uplinkEndpoints: [mockCloudConfigUrl1],
|
|
334
329
|
});
|
|
335
|
-
// for testing purposes, a short pollInterval is ideal so we'll override here
|
|
336
|
-
gateway['pollIntervalInMs'] = 100;
|
|
337
330
|
|
|
338
331
|
gateway.onSchemaChange(onChange);
|
|
339
332
|
await gateway.load(mockApolloConfig);
|
|
@@ -408,8 +401,6 @@ describe('Downstream service health checks', () => {
|
|
|
408
401
|
logger,
|
|
409
402
|
uplinkEndpoints: [mockCloudConfigUrl1],
|
|
410
403
|
});
|
|
411
|
-
// for testing purposes, a short pollInterval is ideal so we'll override here
|
|
412
|
-
gateway['pollIntervalInMs'] = 100;
|
|
413
404
|
|
|
414
405
|
await gateway.load(mockApolloConfig);
|
|
415
406
|
await gateway.stop();
|
|
@@ -482,8 +473,6 @@ describe('Downstream service health checks', () => {
|
|
|
482
473
|
logger,
|
|
483
474
|
uplinkEndpoints: [mockCloudConfigUrl1],
|
|
484
475
|
});
|
|
485
|
-
// for testing purposes, a short pollInterval is ideal so we'll override here
|
|
486
|
-
gateway['pollIntervalInMs'] = 100;
|
|
487
476
|
|
|
488
477
|
gateway.onSchemaChange(onChange);
|
|
489
478
|
await gateway.load(mockApolloConfig);
|
|
@@ -526,8 +515,6 @@ describe('Downstream service health checks', () => {
|
|
|
526
515
|
logger,
|
|
527
516
|
uplinkEndpoints: [mockCloudConfigUrl1],
|
|
528
517
|
});
|
|
529
|
-
// for testing purposes, a short pollInterval is ideal so we'll override here
|
|
530
|
-
gateway['pollIntervalInMs'] = 100;
|
|
531
518
|
|
|
532
519
|
const updateSpy = jest.fn();
|
|
533
520
|
gateway.onSchemaLoadOrUpdate(() => updateSpy());
|
package/src/config.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { GraphQLError, GraphQLSchema } from 'graphql';
|
|
2
|
-
import { HeadersInit } from 'node-fetch';
|
|
3
|
-
import {
|
|
2
|
+
import type { HeadersInit } from 'node-fetch';
|
|
3
|
+
import { GatewayGraphQLRequestContext } from '@apollo/server-gateway-interface';
|
|
4
4
|
import type { Logger } from '@apollo/utils.logger';
|
|
5
5
|
import { GraphQLDataSource } from './datasources/types';
|
|
6
|
-
import { QueryPlan } from '@apollo/query-planner';
|
|
6
|
+
import { QueryPlan, QueryPlannerConfig } from '@apollo/query-planner';
|
|
7
7
|
import { OperationContext } from './operationContext';
|
|
8
8
|
import { ServiceMap } from './executeQueryPlan';
|
|
9
9
|
import { ServiceDefinition } from "@apollo/federation-internals";
|
|
@@ -21,9 +21,7 @@ export type Experimental_DidResolveQueryPlanCallback = ({
|
|
|
21
21
|
readonly queryPlan: QueryPlan;
|
|
22
22
|
readonly serviceMap: ServiceMap;
|
|
23
23
|
readonly operationContext: OperationContext;
|
|
24
|
-
readonly requestContext:
|
|
25
|
-
Record<string, any>
|
|
26
|
-
>;
|
|
24
|
+
readonly requestContext: GatewayGraphQLRequestContext;
|
|
27
25
|
}) => void;
|
|
28
26
|
|
|
29
27
|
interface ImplementingServiceLocation {
|
|
@@ -129,6 +127,8 @@ interface GatewayConfigBase {
|
|
|
129
127
|
experimental_autoFragmentization?: boolean;
|
|
130
128
|
fetcher?: Fetcher;
|
|
131
129
|
serviceHealthCheck?: boolean;
|
|
130
|
+
|
|
131
|
+
queryPlannerConfig?: QueryPlannerConfig;
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
// TODO(trevor:removeServiceList)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GatewayGraphQLResponse } from '@apollo/server-gateway-interface';
|
|
2
2
|
import {
|
|
3
3
|
GraphQLSchema,
|
|
4
4
|
graphql,
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
DocumentNode,
|
|
7
7
|
parse,
|
|
8
8
|
} from 'graphql';
|
|
9
|
-
import { enablePluginsForSchemaResolvers } from 'apollo-server-core/dist/utils/schemaInstrumentation';
|
|
10
9
|
import { GraphQLDataSource, GraphQLDataSourceProcessOptions } from './types';
|
|
11
10
|
|
|
12
11
|
export class LocalGraphQLDataSource<
|
|
@@ -14,13 +13,12 @@ export class LocalGraphQLDataSource<
|
|
|
14
13
|
> implements GraphQLDataSource<TContext>
|
|
15
14
|
{
|
|
16
15
|
constructor(public readonly schema: GraphQLSchema) {
|
|
17
|
-
enablePluginsForSchemaResolvers(schema);
|
|
18
16
|
}
|
|
19
17
|
|
|
20
18
|
async process({
|
|
21
19
|
request,
|
|
22
20
|
context,
|
|
23
|
-
}: GraphQLDataSourceProcessOptions<TContext>): Promise<
|
|
21
|
+
}: GraphQLDataSourceProcessOptions<TContext>): Promise<GatewayGraphQLResponse> {
|
|
24
22
|
return graphql({
|
|
25
23
|
schema: this.schema,
|
|
26
24
|
source: request.query!,
|