@apollo/gateway 0.46.0-alpha.0 → 0.48.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.
- package/dist/datasources/LocalGraphQLDataSource.js.map +1 -1
- package/dist/datasources/RemoteGraphQLDataSource.d.ts.map +1 -1
- package/dist/datasources/RemoteGraphQLDataSource.js +4 -1
- package/dist/datasources/RemoteGraphQLDataSource.js.map +1 -1
- package/dist/executeQueryPlan.d.ts.map +1 -1
- package/dist/executeQueryPlan.js +1 -1
- 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 +4 -2
- package/dist/index.js.map +1 -1
- package/dist/schema-helper/addResolversToSchema.d.ts +4 -0
- package/dist/schema-helper/addResolversToSchema.d.ts.map +1 -0
- package/dist/schema-helper/addResolversToSchema.js +62 -0
- package/dist/schema-helper/addResolversToSchema.js.map +1 -0
- package/dist/schema-helper/error.d.ts +6 -0
- package/dist/schema-helper/error.d.ts.map +1 -0
- package/dist/schema-helper/error.js +14 -0
- package/dist/schema-helper/error.js.map +1 -0
- package/dist/schema-helper/index.d.ts +4 -0
- package/dist/schema-helper/index.d.ts.map +1 -0
- package/dist/schema-helper/index.js +16 -0
- package/dist/schema-helper/index.js.map +1 -0
- package/dist/schema-helper/resolverMap.d.ts +16 -0
- package/dist/schema-helper/resolverMap.d.ts.map +1 -0
- package/dist/schema-helper/resolverMap.js +3 -0
- package/dist/schema-helper/resolverMap.js.map +1 -0
- package/dist/supergraphManagers/LegacyFetcher/index.js +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 +11 -10
- package/src/__mocks__/make-fetch-happen-fetcher.ts +3 -1
- package/src/__tests__/executeQueryPlan.test.ts +1 -1
- package/src/__tests__/execution-utils.ts +1 -1
- package/src/__tests__/gateway/buildService.test.ts +1 -1
- package/src/__tests__/gateway/endToEnd.test.ts +1 -1
- package/src/__tests__/gateway/executor.test.ts +1 -1
- package/src/__tests__/gateway/reporting.test.ts +40 -13
- package/src/__tests__/gateway/supergraphSdl.test.ts +6 -2
- package/src/__tests__/integration/nockMocks.ts +3 -2
- package/src/datasources/LocalGraphQLDataSource.ts +1 -1
- package/src/datasources/RemoteGraphQLDataSource.ts +8 -2
- package/src/datasources/__tests__/LocalGraphQLDataSource.test.ts +1 -1
- package/src/datasources/__tests__/RemoteGraphQLDataSource.test.ts +4 -4
- package/src/executeQueryPlan.ts +3 -1
- package/src/index.ts +4 -1
- package/src/schema-helper/addResolversToSchema.ts +83 -0
- package/src/schema-helper/error.ts +11 -0
- package/src/schema-helper/index.ts +3 -0
- package/src/schema-helper/resolverMap.ts +23 -0
- 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
- package/src/utilities/__tests__/cleanErrorOfInaccessibleElements.test.ts +5 -5
- package/CHANGELOG.md +0 -495
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.loadSupergraphSdlFromStorage = exports.loadSupergraphSdlFromUplinks = exports.SUPERGRAPH_SDL_QUERY = void 0;
|
|
6
|
+
exports.loadSupergraphSdlFromStorage = exports.loadSupergraphSdlFromUplinks = exports.UplinkFetcherError = exports.SUPERGRAPH_SDL_QUERY = void 0;
|
|
4
7
|
const apollo_server_env_1 = require("apollo-server-env");
|
|
8
|
+
const async_retry_1 = __importDefault(require("async-retry"));
|
|
5
9
|
const outOfBandReporter_1 = require("./outOfBandReporter");
|
|
6
10
|
exports.SUPERGRAPH_SDL_QUERY = `#graphql
|
|
7
11
|
query SupergraphSdl($apiKey: String!, $ref: String!, $ifAfterId: ID) {
|
|
@@ -20,30 +24,24 @@ exports.SUPERGRAPH_SDL_QUERY = `#graphql
|
|
|
20
24
|
`;
|
|
21
25
|
const { name, version } = require('../../../package.json');
|
|
22
26
|
const fetchErrorMsg = "An error occurred while fetching your schema from Apollo: ";
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
let result = null;
|
|
28
|
-
while (retries++ <= maxRetries && result == null) {
|
|
29
|
-
try {
|
|
30
|
-
result = await loadSupergraphSdlFromStorage({
|
|
31
|
-
graphRef,
|
|
32
|
-
apiKey,
|
|
33
|
-
endpoint: endpoints[fetchCounter++ % endpoints.length],
|
|
34
|
-
errorReportingEndpoint,
|
|
35
|
-
fetcher,
|
|
36
|
-
compositionId
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
catch (e) {
|
|
40
|
-
lastException = e;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
if (result === null && lastException !== null) {
|
|
44
|
-
throw lastException;
|
|
27
|
+
class UplinkFetcherError extends Error {
|
|
28
|
+
constructor(message) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = 'UplinkFetcherError';
|
|
45
31
|
}
|
|
46
|
-
|
|
32
|
+
}
|
|
33
|
+
exports.UplinkFetcherError = UplinkFetcherError;
|
|
34
|
+
async function loadSupergraphSdlFromUplinks({ graphRef, apiKey, endpoints, errorReportingEndpoint, fetcher, compositionId, maxRetries, roundRobinSeed, }) {
|
|
35
|
+
return (0, async_retry_1.default)(() => loadSupergraphSdlFromStorage({
|
|
36
|
+
graphRef,
|
|
37
|
+
apiKey,
|
|
38
|
+
endpoint: endpoints[roundRobinSeed++ % endpoints.length],
|
|
39
|
+
errorReportingEndpoint,
|
|
40
|
+
fetcher,
|
|
41
|
+
compositionId,
|
|
42
|
+
}), {
|
|
43
|
+
retries: maxRetries,
|
|
44
|
+
});
|
|
47
45
|
}
|
|
48
46
|
exports.loadSupergraphSdlFromUplinks = loadSupergraphSdlFromUplinks;
|
|
49
47
|
async function loadSupergraphSdlFromStorage({ graphRef, apiKey, endpoint, errorReportingEndpoint, fetcher, compositionId, }) {
|
|
@@ -81,7 +79,7 @@ async function loadSupergraphSdlFromStorage({ graphRef, apiKey, endpoint, errorR
|
|
|
81
79
|
endedAt: endTime,
|
|
82
80
|
fetcher,
|
|
83
81
|
});
|
|
84
|
-
throw new
|
|
82
|
+
throw new UplinkFetcherError(fetchErrorMsg + ((_a = e.message) !== null && _a !== void 0 ? _a : e));
|
|
85
83
|
}
|
|
86
84
|
const endTime = new Date();
|
|
87
85
|
let response;
|
|
@@ -90,15 +88,15 @@ async function loadSupergraphSdlFromStorage({ graphRef, apiKey, endpoint, errorR
|
|
|
90
88
|
response = await result.json();
|
|
91
89
|
}
|
|
92
90
|
catch (e) {
|
|
93
|
-
throw new
|
|
91
|
+
throw new UplinkFetcherError((_b = fetchErrorMsg + result.status + ' ' + e.message) !== null && _b !== void 0 ? _b : e);
|
|
94
92
|
}
|
|
95
93
|
if ('errors' in response) {
|
|
96
|
-
throw new
|
|
94
|
+
throw new UplinkFetcherError([fetchErrorMsg, ...response.errors.map((error) => error.message)].join('\n'));
|
|
97
95
|
}
|
|
98
96
|
}
|
|
99
97
|
else {
|
|
100
98
|
await (0, outOfBandReporter_1.submitOutOfBandReportIfConfigured)({
|
|
101
|
-
error: new
|
|
99
|
+
error: new UplinkFetcherError(fetchErrorMsg + result.status + ' ' + result.statusText),
|
|
102
100
|
request,
|
|
103
101
|
endpoint: errorReportingEndpoint,
|
|
104
102
|
response: result,
|
|
@@ -106,7 +104,7 @@ async function loadSupergraphSdlFromStorage({ graphRef, apiKey, endpoint, errorR
|
|
|
106
104
|
endedAt: endTime,
|
|
107
105
|
fetcher,
|
|
108
106
|
});
|
|
109
|
-
throw new
|
|
107
|
+
throw new UplinkFetcherError(fetchErrorMsg + result.status + ' ' + result.statusText);
|
|
110
108
|
}
|
|
111
109
|
const { routerConfig } = response.data;
|
|
112
110
|
if (routerConfig.__typename === 'RouterConfigResult') {
|
|
@@ -115,13 +113,13 @@ async function loadSupergraphSdlFromStorage({ graphRef, apiKey, endpoint, errorR
|
|
|
115
113
|
}
|
|
116
114
|
else if (routerConfig.__typename === 'FetchError') {
|
|
117
115
|
const { code, message } = routerConfig;
|
|
118
|
-
throw new
|
|
116
|
+
throw new UplinkFetcherError(`${code}: ${message}`);
|
|
119
117
|
}
|
|
120
118
|
else if (routerConfig.__typename === 'Unchanged') {
|
|
121
119
|
return null;
|
|
122
120
|
}
|
|
123
121
|
else {
|
|
124
|
-
throw new
|
|
122
|
+
throw new UplinkFetcherError('Programming error: unhandled response failure');
|
|
125
123
|
}
|
|
126
124
|
}
|
|
127
125
|
exports.loadSupergraphSdlFromStorage = loadSupergraphSdlFromStorage;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadSupergraphSdlFromStorage.js","sourceRoot":"","sources":["../../../src/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loadSupergraphSdlFromStorage.js","sourceRoot":"","sources":["../../../src/supergraphManagers/UplinkFetcher/loadSupergraphSdlFromStorage.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,4 +2,5 @@ export { LocalCompose } from './LocalCompose';
|
|
|
2
2
|
export { LegacyFetcher } from './LegacyFetcher';
|
|
3
3
|
export { IntrospectAndCompose } from './IntrospectAndCompose';
|
|
4
4
|
export { UplinkFetcher } from './UplinkFetcher';
|
|
5
|
+
export { UplinkFetcherError } from './UplinkFetcher/loadSupergraphSdlFromStorage';
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/supergraphManagers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/supergraphManagers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.UplinkFetcher = exports.IntrospectAndCompose = exports.LegacyFetcher = exports.LocalCompose = void 0;
|
|
3
|
+
exports.UplinkFetcherError = exports.UplinkFetcher = exports.IntrospectAndCompose = exports.LegacyFetcher = exports.LocalCompose = void 0;
|
|
4
4
|
var LocalCompose_1 = require("./LocalCompose");
|
|
5
5
|
Object.defineProperty(exports, "LocalCompose", { enumerable: true, get: function () { return LocalCompose_1.LocalCompose; } });
|
|
6
6
|
var LegacyFetcher_1 = require("./LegacyFetcher");
|
|
@@ -9,4 +9,6 @@ var IntrospectAndCompose_1 = require("./IntrospectAndCompose");
|
|
|
9
9
|
Object.defineProperty(exports, "IntrospectAndCompose", { enumerable: true, get: function () { return IntrospectAndCompose_1.IntrospectAndCompose; } });
|
|
10
10
|
var UplinkFetcher_1 = require("./UplinkFetcher");
|
|
11
11
|
Object.defineProperty(exports, "UplinkFetcher", { enumerable: true, get: function () { return UplinkFetcher_1.UplinkFetcher; } });
|
|
12
|
+
var loadSupergraphSdlFromStorage_1 = require("./UplinkFetcher/loadSupergraphSdlFromStorage");
|
|
13
|
+
Object.defineProperty(exports, "UplinkFetcherError", { enumerable: true, get: function () { return loadSupergraphSdlFromStorage_1.UplinkFetcherError; } });
|
|
12
14
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/supergraphManagers/index.ts"],"names":[],"mappings":";;;AAAA,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AACrB,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,+DAA8D;AAArD,4HAAA,oBAAoB,OAAA;AAC7B,iDAAgD;AAAvC,8GAAA,aAAa,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/supergraphManagers/index.ts"],"names":[],"mappings":";;;AAAA,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AACrB,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,+DAA8D;AAArD,4HAAA,oBAAoB,OAAA;AAC7B,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,6FAAiF;AAAxE,kIAAA,kBAAkB,OAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apollo/gateway",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.48.1",
|
|
4
4
|
"description": "Apollo Gateway",
|
|
5
5
|
"author": "Apollo <packages@apollographql.com>",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -26,25 +26,26 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@apollo/core-schema": "^0.2.0",
|
|
29
|
-
"@apollo/federation": "^0.
|
|
30
|
-
"@apollo/query-planner": "^0.
|
|
29
|
+
"@apollo/federation": "^0.35.1",
|
|
30
|
+
"@apollo/query-planner": "^0.8.0",
|
|
31
31
|
"@josephg/resolvable": "^1.0.1",
|
|
32
32
|
"@opentelemetry/api": "^1.0.1",
|
|
33
33
|
"@types/node-fetch": "2.5.12",
|
|
34
|
-
"apollo-
|
|
35
|
-
"apollo-reporting-protobuf": "^0.8.0 || ^3.0.0 || ^3.3.0-alpha.0",
|
|
34
|
+
"apollo-reporting-protobuf": "^0.8.0 || ^3.0.0",
|
|
36
35
|
"apollo-server-caching": "^0.7.0 || ^3.0.0",
|
|
37
|
-
"apollo-server-core": "^2.23.0 || ^3.0.0
|
|
36
|
+
"apollo-server-core": "^2.23.0 || ^3.0.0",
|
|
38
37
|
"apollo-server-env": "^3.0.0 || ^4.0.0",
|
|
39
38
|
"apollo-server-errors": "^2.5.0 || ^3.0.0",
|
|
40
|
-
"apollo-server-types": "^0.9.0 || ^3.0.0
|
|
39
|
+
"apollo-server-types": "^0.9.0 || ^3.0.0",
|
|
40
|
+
"apollo-utilities": "^1.3.0",
|
|
41
|
+
"async-retry": "^1.3.3",
|
|
41
42
|
"loglevel": "^1.6.1",
|
|
42
43
|
"make-fetch-happen": "^8.0.0",
|
|
43
|
-
"pretty-format": "^27.
|
|
44
|
+
"pretty-format": "^27.4.6",
|
|
44
45
|
"sha.js": "^2.4.11"
|
|
45
46
|
},
|
|
46
47
|
"peerDependencies": {
|
|
47
|
-
"graphql": "^15.
|
|
48
|
+
"graphql": "^15.8.0 || ^16.0.0"
|
|
48
49
|
},
|
|
49
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "50e54e6480a863891e28e44e4d7510b3c31d845f"
|
|
50
51
|
}
|
|
@@ -20,6 +20,7 @@ interface MakeFetchHappenMock extends jest.MockedFunction<typeof fetch> {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
const mockMakeFetchHappen = jest.fn(fetcher) as unknown as MakeFetchHappenMock;
|
|
23
|
+
const defaults = () => mockMakeFetchHappen;
|
|
23
24
|
|
|
24
25
|
mockMakeFetchHappen.mockResponseOnce = (
|
|
25
26
|
data?: BodyInit,
|
|
@@ -47,7 +48,8 @@ mockMakeFetchHappen.mockJSONResponseOnce = (
|
|
|
47
48
|
};
|
|
48
49
|
|
|
49
50
|
const makeFetchMock = {
|
|
50
|
-
|
|
51
|
+
fetch: mockMakeFetchHappen,
|
|
52
|
+
defaults,
|
|
51
53
|
};
|
|
52
54
|
|
|
53
55
|
jest.doMock('make-fetch-happen', () => makeFetchMock);
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
GraphQLSchema,
|
|
6
6
|
print,
|
|
7
7
|
} from 'graphql';
|
|
8
|
-
import { addResolversToSchema, GraphQLResolverMap } from 'apollo-graphql';
|
|
9
8
|
import gql from 'graphql-tag';
|
|
10
9
|
import { GraphQLRequestContext, VariableValues } from 'apollo-server-types';
|
|
11
10
|
import { AuthenticationError } from 'apollo-server-core';
|
|
@@ -21,6 +20,7 @@ import { buildComposedSchema, QueryPlanner } from '@apollo/query-planner';
|
|
|
21
20
|
import { ApolloGateway } from '..';
|
|
22
21
|
import { ApolloServerBase as ApolloServer } from 'apollo-server-core';
|
|
23
22
|
import { getFederatedTestingSchema } from './execution-utils';
|
|
23
|
+
import { addResolversToSchema, GraphQLResolverMap } from '../schema-helper';
|
|
24
24
|
|
|
25
25
|
expect.addSnapshotSerializer(astSerializer);
|
|
26
26
|
expect.addSnapshotSerializer(queryPlanSerializer);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetch } from '../../__mocks__/
|
|
1
|
+
import { fetch } from '../../__mocks__/make-fetch-happen-fetcher';
|
|
2
2
|
import { ApolloServerBase as ApolloServer } from 'apollo-server-core';
|
|
3
3
|
|
|
4
4
|
import { RemoteGraphQLDataSource } from '../../datasources/RemoteGraphQLDataSource';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { GraphQLSchemaModule } from 'apollo-graphql';
|
|
2
1
|
import { buildSubgraphSchema } from '@apollo/subgraph';
|
|
3
2
|
import { ApolloServer } from 'apollo-server';
|
|
4
3
|
import fetch from 'node-fetch';
|
|
5
4
|
import { ApolloGateway } from '../..';
|
|
6
5
|
import { fixtures } from 'apollo-federation-integration-testsuite';
|
|
7
6
|
import { ApolloServerPluginInlineTrace } from 'apollo-server-core';
|
|
7
|
+
import { GraphQLSchemaModule } from '../../schema-helper';
|
|
8
8
|
|
|
9
9
|
async function startFederatedServer(modules: GraphQLSchemaModule[]) {
|
|
10
10
|
const schema = buildSubgraphSchema(modules);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { fetch } from '../../__mocks__/make-fetch-happen-fetcher';
|
|
1
2
|
import gql from 'graphql-tag';
|
|
2
3
|
import { ApolloGateway } from '../../';
|
|
3
4
|
import { fixtures } from 'apollo-federation-integration-testsuite';
|
|
4
5
|
import { Logger } from 'apollo-server-types';
|
|
5
|
-
import { fetch } from '../../__mocks__/apollo-server-env';
|
|
6
6
|
|
|
7
7
|
let logger: {
|
|
8
8
|
warn: jest.MockedFunction<Logger['warn']>,
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import { gunzipSync } from 'zlib';
|
|
2
2
|
import nock from 'nock';
|
|
3
|
-
import { GraphQLSchemaModule } from 'apollo-graphql';
|
|
4
|
-
import gql from 'graphql-tag';
|
|
5
3
|
import { buildSubgraphSchema } from '@apollo/subgraph';
|
|
6
4
|
import { ApolloServer } from 'apollo-server';
|
|
7
5
|
import { ApolloServerPluginUsageReporting } from 'apollo-server-core';
|
|
8
|
-
import { execute, toPromise } from 'apollo-link';
|
|
9
|
-
import { createHttpLink } from 'apollo-link-http';
|
|
10
6
|
import fetch from 'node-fetch';
|
|
11
7
|
import { ApolloGateway } from '../..';
|
|
12
8
|
import { Plugin, Config, Refs } from 'pretty-format';
|
|
@@ -14,6 +10,7 @@ import { Report, Trace } from 'apollo-reporting-protobuf';
|
|
|
14
10
|
import { fixtures } from 'apollo-federation-integration-testsuite';
|
|
15
11
|
import { nockAfterEach, nockBeforeEach } from '../nockAssertions';
|
|
16
12
|
import resolvable, { Resolvable } from '@josephg/resolvable';
|
|
13
|
+
import { GraphQLSchemaModule } from '../../schema-helper';
|
|
17
14
|
|
|
18
15
|
// Normalize specific fields that change often (eg timestamps) to static values,
|
|
19
16
|
// to make snapshot testing viable. (If these helpers are more generally
|
|
@@ -141,7 +138,7 @@ describe('reporting', () => {
|
|
|
141
138
|
});
|
|
142
139
|
|
|
143
140
|
it(`queries three services`, async () => {
|
|
144
|
-
const query =
|
|
141
|
+
const query = `#graphql
|
|
145
142
|
query {
|
|
146
143
|
me {
|
|
147
144
|
name {
|
|
@@ -155,12 +152,15 @@ describe('reporting', () => {
|
|
|
155
152
|
}
|
|
156
153
|
`;
|
|
157
154
|
|
|
158
|
-
const result = await
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
155
|
+
const result = await fetch(gatewayUrl, {
|
|
156
|
+
method: 'POST',
|
|
157
|
+
headers: {
|
|
158
|
+
'Content-Type': 'application/json',
|
|
159
|
+
},
|
|
160
|
+
body: JSON.stringify({ query }),
|
|
161
|
+
});
|
|
162
|
+
const body = await result.json();
|
|
163
|
+
expect(body).toMatchInlineSnapshot(`
|
|
164
164
|
Object {
|
|
165
165
|
"data": Object {
|
|
166
166
|
"me": Object {
|
|
@@ -231,6 +231,34 @@ describe('reporting', () => {
|
|
|
231
231
|
"tracesPerQuery": Object {
|
|
232
232
|
"# -
|
|
233
233
|
{me{name{first last}}topProducts{name}}": Object {
|
|
234
|
+
"referencedFieldsByType": Object {
|
|
235
|
+
"Name": Object {
|
|
236
|
+
"fieldNames": Array [
|
|
237
|
+
"first",
|
|
238
|
+
"last",
|
|
239
|
+
],
|
|
240
|
+
"isInterface": false,
|
|
241
|
+
},
|
|
242
|
+
"Product": Object {
|
|
243
|
+
"fieldNames": Array [
|
|
244
|
+
"name",
|
|
245
|
+
],
|
|
246
|
+
"isInterface": true,
|
|
247
|
+
},
|
|
248
|
+
"Query": Object {
|
|
249
|
+
"fieldNames": Array [
|
|
250
|
+
"me",
|
|
251
|
+
"topProducts",
|
|
252
|
+
],
|
|
253
|
+
"isInterface": false,
|
|
254
|
+
},
|
|
255
|
+
"User": Object {
|
|
256
|
+
"fieldNames": Array [
|
|
257
|
+
"name",
|
|
258
|
+
],
|
|
259
|
+
"isInterface": false,
|
|
260
|
+
},
|
|
261
|
+
},
|
|
234
262
|
"trace": Array [
|
|
235
263
|
Object {
|
|
236
264
|
"cachePolicy": Object {
|
|
@@ -238,14 +266,13 @@ describe('reporting', () => {
|
|
|
238
266
|
"scope": "PRIVATE",
|
|
239
267
|
},
|
|
240
268
|
"clientName": "",
|
|
241
|
-
"clientReferenceId": "",
|
|
242
269
|
"clientVersion": "",
|
|
243
|
-
"details": Object {},
|
|
244
270
|
"durationNs": 12345,
|
|
245
271
|
"endTime": Object {
|
|
246
272
|
"nanos": 123000000,
|
|
247
273
|
"seconds": "1562203363",
|
|
248
274
|
},
|
|
275
|
+
"fieldExecutionWeight": 1,
|
|
249
276
|
"forbiddenOperation": false,
|
|
250
277
|
"fullQueryCacheHit": false,
|
|
251
278
|
"http": Object {
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ApolloGateway,
|
|
3
|
+
RemoteGraphQLDataSource,
|
|
3
4
|
SubgraphHealthCheckFunction,
|
|
4
5
|
SupergraphSdlUpdateFunction,
|
|
5
6
|
} from '@apollo/gateway';
|
|
6
7
|
import { fixturesWithUpdate } from 'apollo-federation-integration-testsuite';
|
|
7
|
-
import { createHash } from '
|
|
8
|
+
import { createHash } from '../../utilities/createHash';
|
|
8
9
|
import { ApolloServer } from 'apollo-server';
|
|
9
10
|
import { Logger } from 'apollo-server-types';
|
|
10
|
-
import { fetch } from '../../__mocks__/
|
|
11
|
+
import { fetch } from '../../__mocks__/make-fetch-happen-fetcher';
|
|
11
12
|
import { getTestingSupergraphSdl } from '../execution-utils';
|
|
12
13
|
import { mockAllServicesHealthCheckSuccess } from '../integration/nockMocks';
|
|
13
14
|
import resolvable from '@josephg/resolvable';
|
|
@@ -17,6 +18,9 @@ async function getSupergraphSdlGatewayServer() {
|
|
|
17
18
|
const server = new ApolloServer({
|
|
18
19
|
gateway: new ApolloGateway({
|
|
19
20
|
supergraphSdl: getTestingSupergraphSdl(),
|
|
21
|
+
buildService({ url }) {
|
|
22
|
+
return new RemoteGraphQLDataSource({ url, fetcher: fetch });
|
|
23
|
+
}
|
|
20
24
|
}),
|
|
21
25
|
});
|
|
22
26
|
|
|
@@ -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: {
|
|
@@ -39,7 +39,7 @@ export class LocalGraphQLDataSource<
|
|
|
39
39
|
throw new Error(result.errors.map((error) => error.message).join('\n\n'));
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
const sdl = result.data && result.data._service && result.data._service.sdl;
|
|
42
|
+
const sdl = result.data && result.data._service && (result.data._service as any).sdl;
|
|
43
43
|
return parse(sdl);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -17,18 +17,24 @@ import { isObject } from '../utilities/predicates';
|
|
|
17
17
|
import { GraphQLDataSource, GraphQLDataSourceProcessOptions, GraphQLDataSourceRequestKind } from './types';
|
|
18
18
|
import createSHA from 'apollo-server-core/dist/utils/createSHA';
|
|
19
19
|
import { parseCacheControlHeader } from './parseCacheControlHeader';
|
|
20
|
-
|
|
20
|
+
import fetcher from 'make-fetch-happen';
|
|
21
21
|
export class RemoteGraphQLDataSource<
|
|
22
22
|
TContext extends Record<string, any> = Record<string, any>,
|
|
23
23
|
> implements GraphQLDataSource<TContext>
|
|
24
24
|
{
|
|
25
|
-
fetcher: typeof fetch
|
|
25
|
+
fetcher: typeof fetch;
|
|
26
26
|
|
|
27
27
|
constructor(
|
|
28
28
|
config?: Partial<RemoteGraphQLDataSource<TContext>> &
|
|
29
29
|
object &
|
|
30
30
|
ThisType<RemoteGraphQLDataSource<TContext>>,
|
|
31
31
|
) {
|
|
32
|
+
this.fetcher = fetcher.defaults({
|
|
33
|
+
// although this is the default, we want to take extra care and be very
|
|
34
|
+
// explicity to ensure that mutations cannot be retried. please leave this
|
|
35
|
+
// intact.
|
|
36
|
+
retry: false,
|
|
37
|
+
});
|
|
32
38
|
if (config) {
|
|
33
39
|
return Object.assign(this, config);
|
|
34
40
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LocalGraphQLDataSource } from '../LocalGraphQLDataSource';
|
|
2
2
|
import { buildSubgraphSchema } from '@apollo/subgraph';
|
|
3
3
|
import gql from 'graphql-tag';
|
|
4
|
-
import { GraphQLResolverMap } from '
|
|
4
|
+
import { GraphQLResolverMap } from '../../schema-helper';
|
|
5
5
|
import { GraphQLRequestContext } from 'apollo-server-types';
|
|
6
6
|
import { GraphQLDataSourceRequestKind } from '../types';
|
|
7
7
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { fetch } from '../../__mocks__/apollo-server-env';
|
|
2
|
-
import {
|
|
1
|
+
import { fetch as customFetcher } from '../../__mocks__/apollo-server-env';
|
|
2
|
+
import { fetch } from '../../__mocks__/make-fetch-happen-fetcher';
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
ApolloError,
|
|
@@ -263,8 +263,8 @@ describe('fetcher', () => {
|
|
|
263
263
|
expect(data).toEqual({ injected: true });
|
|
264
264
|
});
|
|
265
265
|
|
|
266
|
-
it('supports a custom fetcher, like `
|
|
267
|
-
const injectedFetch =
|
|
266
|
+
it('supports a custom fetcher, like `node-fetch`', async () => {
|
|
267
|
+
const injectedFetch = customFetcher.mockJSONResponseOnce({
|
|
268
268
|
data: { me: 'james' },
|
|
269
269
|
});
|
|
270
270
|
const DataSource = new RemoteGraphQLDataSource({
|
package/src/executeQueryPlan.ts
CHANGED
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
GraphQLFieldResolver,
|
|
13
13
|
GraphQLFormattedError,
|
|
14
14
|
isAbstractType,
|
|
15
|
+
isObjectType,
|
|
16
|
+
isInterfaceType,
|
|
15
17
|
GraphQLSchema,
|
|
16
18
|
} from 'graphql';
|
|
17
19
|
import { Trace, google } from 'apollo-reporting-protobuf';
|
|
@@ -590,7 +592,7 @@ function doesTypeConditionMatch(
|
|
|
590
592
|
}
|
|
591
593
|
|
|
592
594
|
if (isAbstractType(conditionalType)) {
|
|
593
|
-
return schema.isSubType(conditionalType, type);
|
|
595
|
+
return (isObjectType(type) || isInterfaceType(type)) && schema.isSubType(conditionalType, type);
|
|
594
596
|
}
|
|
595
597
|
|
|
596
598
|
return false;
|
package/src/index.ts
CHANGED
|
@@ -400,7 +400,7 @@ export class ApolloGateway implements GraphQLService {
|
|
|
400
400
|
apiKey: this.apolloConfig!.key!,
|
|
401
401
|
uplinkEndpoints,
|
|
402
402
|
maxRetries:
|
|
403
|
-
this.config.uplinkMaxRetries ?? uplinkEndpoints.length * 3,
|
|
403
|
+
this.config.uplinkMaxRetries ?? uplinkEndpoints.length * 3 - 1, // -1 for the initial request
|
|
404
404
|
subgraphHealthCheck: this.config.serviceHealthCheck,
|
|
405
405
|
fetcher: this.fetcher,
|
|
406
406
|
logger: this.logger,
|
|
@@ -1144,3 +1144,6 @@ export {
|
|
|
1144
1144
|
SupergraphSdlHook,
|
|
1145
1145
|
SupergraphManager
|
|
1146
1146
|
} from './config';
|
|
1147
|
+
|
|
1148
|
+
export { UplinkFetcherError } from "./supergraphManagers"
|
|
1149
|
+
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GraphQLSchema,
|
|
3
|
+
isObjectType,
|
|
4
|
+
GraphQLEnumType,
|
|
5
|
+
isAbstractType,
|
|
6
|
+
isScalarType,
|
|
7
|
+
isEnumType,
|
|
8
|
+
GraphQLEnumValueConfig,
|
|
9
|
+
} from 'graphql';
|
|
10
|
+
|
|
11
|
+
import { GraphQLResolverMap } from './resolverMap';
|
|
12
|
+
|
|
13
|
+
export function addResolversToSchema(
|
|
14
|
+
schema: GraphQLSchema,
|
|
15
|
+
resolvers: GraphQLResolverMap<any>
|
|
16
|
+
) {
|
|
17
|
+
for (const [typeName, fieldConfigs] of Object.entries(resolvers)) {
|
|
18
|
+
const type = schema.getType(typeName);
|
|
19
|
+
|
|
20
|
+
if (isAbstractType(type)) {
|
|
21
|
+
for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) {
|
|
22
|
+
if (fieldName.startsWith("__")) {
|
|
23
|
+
(type as any)[fieldName.substring(2)] = fieldConfig;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (isScalarType(type)) {
|
|
29
|
+
for (const fn in fieldConfigs) {
|
|
30
|
+
(type as any)[fn] = (fieldConfigs as any)[fn];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (isEnumType(type)) {
|
|
35
|
+
const values = type.getValues();
|
|
36
|
+
const newValues: { [key: string]: GraphQLEnumValueConfig } = {};
|
|
37
|
+
values.forEach(value => {
|
|
38
|
+
let newValue = (fieldConfigs as any)[value.name];
|
|
39
|
+
if (newValue === undefined) {
|
|
40
|
+
newValue = value.name;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
newValues[value.name] = {
|
|
44
|
+
value: newValue,
|
|
45
|
+
deprecationReason: value.deprecationReason,
|
|
46
|
+
description: value.description,
|
|
47
|
+
astNode: value.astNode,
|
|
48
|
+
extensions: undefined
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// In place updating hack to get around pulling in the full
|
|
53
|
+
// schema walking and immutable updating machinery from graphql-tools
|
|
54
|
+
Object.assign(
|
|
55
|
+
type,
|
|
56
|
+
new GraphQLEnumType({
|
|
57
|
+
...type.toConfig(),
|
|
58
|
+
values: newValues
|
|
59
|
+
})
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!isObjectType(type)) continue;
|
|
64
|
+
|
|
65
|
+
const fieldMap = type.getFields();
|
|
66
|
+
|
|
67
|
+
for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) {
|
|
68
|
+
if (fieldName.startsWith("__")) {
|
|
69
|
+
(type as any)[fieldName.substring(2)] = fieldConfig;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const field = fieldMap[fieldName];
|
|
74
|
+
if (!field) continue;
|
|
75
|
+
|
|
76
|
+
if (typeof fieldConfig === "function") {
|
|
77
|
+
field.resolve = fieldConfig;
|
|
78
|
+
} else {
|
|
79
|
+
field.resolve = fieldConfig.resolve;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { GraphQLError } from "graphql";
|
|
2
|
+
|
|
3
|
+
export class GraphQLSchemaValidationError extends Error {
|
|
4
|
+
constructor(public errors: ReadonlyArray<GraphQLError>) {
|
|
5
|
+
super();
|
|
6
|
+
|
|
7
|
+
this.name = this.constructor.name;
|
|
8
|
+
Error.captureStackTrace(this, this.constructor);
|
|
9
|
+
this.message = errors.map(error => error.message).join("\n\n");
|
|
10
|
+
}
|
|
11
|
+
}
|