@apollo/gateway 2.1.0-alpha.2 → 2.1.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/dist/config.d.ts +2 -2
- 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/RemoteGraphQLDataSource.d.ts +4 -4
- package/dist/datasources/RemoteGraphQLDataSource.d.ts.map +1 -1
- package/dist/datasources/RemoteGraphQLDataSource.js +5 -4
- package/dist/datasources/RemoteGraphQLDataSource.js.map +1 -1
- package/dist/datasources/types.d.ts +6 -6
- package/dist/datasources/types.d.ts.map +1 -1
- package/dist/executeQueryPlan.d.ts +2 -2
- package/dist/executeQueryPlan.d.ts.map +1 -1
- package/dist/executeQueryPlan.js +6 -0
- package/dist/executeQueryPlan.js.map +1 -1
- package/dist/index.d.ts +7 -8
- package/dist/index.d.ts.map +1 -1
- 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/schema-helper/addExtensions.d.ts.map +1 -1
- package/dist/schema-helper/addExtensions.js +6 -3
- package/dist/schema-helper/addExtensions.js.map +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 +2 -2
- package/dist/supergraphManagers/UplinkSupergraphManager/index.d.ts.map +1 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/index.js.map +1 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/loadSupergraphSdlFromStorage.d.ts +1 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/loadSupergraphSdlFromStorage.d.ts.map +1 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/outOfBandReporter.d.ts +1 -2
- package/dist/supergraphManagers/UplinkSupergraphManager/outOfBandReporter.d.ts.map +1 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/outOfBandReporter.js.map +1 -1
- package/package.json +8 -10
- package/src/__tests__/executeQueryPlan.test.ts +143 -7
- package/src/__tests__/execution-utils.ts +3 -3
- package/src/__tests__/gateway/executor.test.ts +2 -2
- package/src/__tests__/gateway/lifecycle-hooks.test.ts +1 -1
- package/src/__tests__/integration/managed.test.ts +3 -2
- package/src/config.ts +2 -4
- package/src/datasources/LocalGraphQLDataSource.ts +2 -2
- package/src/datasources/RemoteGraphQLDataSource.ts +18 -24
- package/src/datasources/__tests__/LocalGraphQLDataSource.test.ts +2 -2
- package/src/datasources/__tests__/RemoteGraphQLDataSource.test.ts +5 -5
- package/src/datasources/types.ts +6 -6
- package/src/executeQueryPlan.ts +19 -16
- package/src/index.ts +10 -14
- package/src/logger.ts +1 -1
- package/src/schema-helper/__tests__/addExtensions.test.ts +54 -0
- package/src/schema-helper/addExtensions.ts +8 -2
- package/src/supergraphManagers/IntrospectAndCompose/loadServicesFromRemoteEndpoint.ts +2 -2
- package/src/supergraphManagers/UplinkSupergraphManager/__tests__/loadSupergraphSdlFromStorage.test.ts +46 -2
- package/src/supergraphManagers/UplinkSupergraphManager/index.ts +3 -3
- package/src/supergraphManagers/UplinkSupergraphManager/loadSupergraphSdlFromStorage.ts +5 -5
- package/src/supergraphManagers/UplinkSupergraphManager/outOfBandReporter.ts +1 -2
- package/dist/supergraphManagers/UplinkSupergraphManager/types.d.ts +0 -9
- package/dist/supergraphManagers/UplinkSupergraphManager/types.d.ts.map +0 -1
- package/dist/supergraphManagers/UplinkSupergraphManager/types.js +0 -5
- package/dist/supergraphManagers/UplinkSupergraphManager/types.js.map +0 -1
- package/src/supergraphManagers/UplinkSupergraphManager/types.ts +0 -10
package/src/datasources/types.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GatewayGraphQLResponse, GatewayGraphQLRequestContext } from '@apollo/server-gateway-interface';
|
|
2
2
|
|
|
3
3
|
export interface GraphQLDataSource<
|
|
4
4
|
TContext extends Record<string, any> = Record<string, any>,
|
|
5
5
|
> {
|
|
6
6
|
process(
|
|
7
7
|
options: GraphQLDataSourceProcessOptions<TContext>,
|
|
8
|
-
): Promise<
|
|
8
|
+
): Promise<GatewayGraphQLResponse>;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export enum GraphQLDataSourceRequestKind {
|
|
@@ -20,7 +20,7 @@ export type GraphQLDataSourceProcessOptions<
|
|
|
20
20
|
/**
|
|
21
21
|
* The request to send to the subgraph.
|
|
22
22
|
*/
|
|
23
|
-
request:
|
|
23
|
+
request: GatewayGraphQLRequestContext<TContext>['request'];
|
|
24
24
|
} & (
|
|
25
25
|
| {
|
|
26
26
|
kind: GraphQLDataSourceRequestKind.INCOMING_OPERATION;
|
|
@@ -29,7 +29,7 @@ export type GraphQLDataSourceProcessOptions<
|
|
|
29
29
|
* one of the strings if this operation is generated by the gateway without an
|
|
30
30
|
* incoming request.
|
|
31
31
|
*/
|
|
32
|
-
incomingRequestContext:
|
|
32
|
+
incomingRequestContext: GatewayGraphQLRequestContext<TContext>;
|
|
33
33
|
/**
|
|
34
34
|
* Equivalent to incomingRequestContext.context (provided here for
|
|
35
35
|
* backwards compatibility): the object created by the Apollo Server
|
|
@@ -38,11 +38,11 @@ export type GraphQLDataSourceProcessOptions<
|
|
|
38
38
|
* @deprecated Use `incomingRequestContext.context` instead (after
|
|
39
39
|
* checking `kind`).
|
|
40
40
|
*/
|
|
41
|
-
context:
|
|
41
|
+
context: GatewayGraphQLRequestContext<TContext>['context'];
|
|
42
42
|
/**
|
|
43
43
|
* The document representation of the request's query being sent to the subgraph, if available.
|
|
44
44
|
*/
|
|
45
|
-
document?:
|
|
45
|
+
document?: GatewayGraphQLRequestContext<TContext>['document'];
|
|
46
46
|
}
|
|
47
47
|
| {
|
|
48
48
|
kind:
|
package/src/executeQueryPlan.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
GraphQLExecutionResult,
|
|
3
|
-
GraphQLRequestContext,
|
|
4
|
-
} from 'apollo-server-types';
|
|
5
1
|
import { Headers } from 'node-fetch';
|
|
6
2
|
import {
|
|
7
3
|
execute,
|
|
@@ -33,7 +29,8 @@ import { deepMerge } from './utilities/deepMerge';
|
|
|
33
29
|
import { isNotNullOrUndefined } from './utilities/array';
|
|
34
30
|
import { SpanStatusCode } from "@opentelemetry/api";
|
|
35
31
|
import { OpenTelemetrySpanNames, tracer } from "./utilities/opentelemetry";
|
|
36
|
-
import { defaultRootName, errorCodeDef, ERRORS } from '@apollo/federation-internals';
|
|
32
|
+
import { assert, defaultRootName, errorCodeDef, ERRORS } from '@apollo/federation-internals';
|
|
33
|
+
import { GatewayGraphQLRequestContext, GatewayExecutionResult } from '@apollo/server-gateway-interface';
|
|
37
34
|
|
|
38
35
|
export type ServiceMap = {
|
|
39
36
|
[serviceName: string]: GraphQLDataSource;
|
|
@@ -41,22 +38,22 @@ export type ServiceMap = {
|
|
|
41
38
|
|
|
42
39
|
type ResultMap = Record<string, any>;
|
|
43
40
|
|
|
44
|
-
interface ExecutionContext
|
|
41
|
+
interface ExecutionContext {
|
|
45
42
|
queryPlan: QueryPlan;
|
|
46
43
|
operationContext: OperationContext;
|
|
47
44
|
serviceMap: ServiceMap;
|
|
48
|
-
requestContext:
|
|
45
|
+
requestContext: GatewayGraphQLRequestContext;
|
|
49
46
|
supergraphSchema: GraphQLSchema;
|
|
50
47
|
errors: GraphQLError[];
|
|
51
48
|
}
|
|
52
49
|
|
|
53
|
-
export async function executeQueryPlan
|
|
50
|
+
export async function executeQueryPlan(
|
|
54
51
|
queryPlan: QueryPlan,
|
|
55
52
|
serviceMap: ServiceMap,
|
|
56
|
-
requestContext:
|
|
53
|
+
requestContext: GatewayGraphQLRequestContext,
|
|
57
54
|
operationContext: OperationContext,
|
|
58
55
|
supergraphSchema: GraphQLSchema,
|
|
59
|
-
): Promise<
|
|
56
|
+
): Promise<GatewayExecutionResult> {
|
|
60
57
|
|
|
61
58
|
const logger = requestContext.logger || console;
|
|
62
59
|
|
|
@@ -64,7 +61,7 @@ export async function executeQueryPlan<TContext>(
|
|
|
64
61
|
try {
|
|
65
62
|
const errors: GraphQLError[] = [];
|
|
66
63
|
|
|
67
|
-
const context: ExecutionContext
|
|
64
|
+
const context: ExecutionContext = {
|
|
68
65
|
queryPlan,
|
|
69
66
|
operationContext,
|
|
70
67
|
serviceMap,
|
|
@@ -170,8 +167,8 @@ export async function executeQueryPlan<TContext>(
|
|
|
170
167
|
// we're going to ignore it, because it makes the code much simpler and more
|
|
171
168
|
// typesafe. However, it doesn't actually ask for traces from the backend
|
|
172
169
|
// service unless we are capturing traces for Studio.
|
|
173
|
-
async function executeNode
|
|
174
|
-
context: ExecutionContext
|
|
170
|
+
async function executeNode(
|
|
171
|
+
context: ExecutionContext,
|
|
175
172
|
node: PlanNode,
|
|
176
173
|
results: ResultMap | ResultMap[],
|
|
177
174
|
path: ResponsePath,
|
|
@@ -251,11 +248,17 @@ async function executeNode<TContext>(
|
|
|
251
248
|
}
|
|
252
249
|
return new Trace.QueryPlanNode({ fetch: traceNode });
|
|
253
250
|
}
|
|
251
|
+
case 'Defer': {
|
|
252
|
+
assert(false, `@defer support is not available in the gateway`);
|
|
253
|
+
}
|
|
254
|
+
case 'Condition': {
|
|
255
|
+
assert(false, `Condition nodes are not available in the gateway`);
|
|
256
|
+
}
|
|
254
257
|
}
|
|
255
258
|
}
|
|
256
259
|
|
|
257
|
-
async function executeFetch
|
|
258
|
-
context: ExecutionContext
|
|
260
|
+
async function executeFetch(
|
|
261
|
+
context: ExecutionContext,
|
|
259
262
|
fetch: FetchNode,
|
|
260
263
|
results: ResultMap | (ResultMap | null | undefined)[],
|
|
261
264
|
_path: ResponsePath,
|
|
@@ -379,7 +382,7 @@ async function executeFetch<TContext>(
|
|
|
379
382
|
}
|
|
380
383
|
});
|
|
381
384
|
async function sendOperation(
|
|
382
|
-
context: ExecutionContext
|
|
385
|
+
context: ExecutionContext,
|
|
383
386
|
source: string,
|
|
384
387
|
variables: Record<string, any>,
|
|
385
388
|
operationName: string | undefined,
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import { deprecate } from 'util';
|
|
2
|
-
import { GraphQLService, Unsubscriber } from 'apollo-server-core';
|
|
3
|
-
import {
|
|
4
|
-
GraphQLExecutionResult,
|
|
5
|
-
GraphQLRequestContextExecutionDidStart,
|
|
6
|
-
} from 'apollo-server-types';
|
|
7
2
|
import { createHash } from '@apollo/utils.createhash';
|
|
8
3
|
import type { Logger } from '@apollo/utils.logger';
|
|
9
4
|
import LRUCache from 'lru-cache';
|
|
@@ -63,6 +58,7 @@ import {
|
|
|
63
58
|
ServiceDefinition,
|
|
64
59
|
} from '@apollo/federation-internals';
|
|
65
60
|
import { getDefaultLogger } from './logger';
|
|
61
|
+
import {GatewayInterface, GatewayUnsubscriber, GatewayGraphQLRequestContext, GatewayExecutionResult} from '@apollo/server-gateway-interface';
|
|
66
62
|
|
|
67
63
|
type DataSourceMap = {
|
|
68
64
|
[serviceName: string]: { url?: string; dataSource: GraphQLDataSource };
|
|
@@ -118,7 +114,7 @@ interface GraphQLServiceEngineConfig {
|
|
|
118
114
|
graphVariant?: string;
|
|
119
115
|
}
|
|
120
116
|
|
|
121
|
-
export class ApolloGateway implements
|
|
117
|
+
export class ApolloGateway implements GatewayInterface {
|
|
122
118
|
public schema?: GraphQLSchema;
|
|
123
119
|
// Same as a `schema` but as a `Schema` to avoid reconverting when we need it.
|
|
124
120
|
// TODO(sylvain): if we add caching in `Schema.toGraphQLJSSchema`, we could maybe only keep `apiSchema`
|
|
@@ -651,7 +647,7 @@ export class ApolloGateway implements GraphQLService {
|
|
|
651
647
|
*/
|
|
652
648
|
public onSchemaChange(
|
|
653
649
|
callback: (schema: GraphQLSchema) => void,
|
|
654
|
-
):
|
|
650
|
+
): GatewayUnsubscriber {
|
|
655
651
|
this.onSchemaChangeListeners.add(callback);
|
|
656
652
|
|
|
657
653
|
return () => {
|
|
@@ -664,7 +660,7 @@ export class ApolloGateway implements GraphQLService {
|
|
|
664
660
|
apiSchema: GraphQLSchema;
|
|
665
661
|
coreSupergraphSdl: string;
|
|
666
662
|
}) => void,
|
|
667
|
-
):
|
|
663
|
+
): GatewayUnsubscriber {
|
|
668
664
|
this.onSchemaLoadOrUpdateListeners.add(callback);
|
|
669
665
|
|
|
670
666
|
return () => {
|
|
@@ -744,9 +740,9 @@ export class ApolloGateway implements GraphQLService {
|
|
|
744
740
|
// ApolloServerPluginUsageReporting) assumes that. In fact, errors talking to backends
|
|
745
741
|
// are unlikely to show up as GraphQLErrors. Do we need to use
|
|
746
742
|
// formatApolloErrors or something?
|
|
747
|
-
public executor = async
|
|
748
|
-
requestContext:
|
|
749
|
-
): Promise<
|
|
743
|
+
public executor = async (
|
|
744
|
+
requestContext: GatewayGraphQLRequestContext,
|
|
745
|
+
): Promise<GatewayExecutionResult> => {
|
|
750
746
|
const spanAttributes = requestContext.operationName
|
|
751
747
|
? { operationName: requestContext.operationName }
|
|
752
748
|
: {};
|
|
@@ -824,7 +820,7 @@ export class ApolloGateway implements GraphQLService {
|
|
|
824
820
|
});
|
|
825
821
|
}
|
|
826
822
|
|
|
827
|
-
const response = await executeQueryPlan
|
|
823
|
+
const response = await executeQueryPlan(
|
|
828
824
|
queryPlan,
|
|
829
825
|
serviceMap,
|
|
830
826
|
requestContext,
|
|
@@ -882,8 +878,8 @@ export class ApolloGateway implements GraphQLService {
|
|
|
882
878
|
);
|
|
883
879
|
};
|
|
884
880
|
|
|
885
|
-
private validateIncomingRequest
|
|
886
|
-
requestContext:
|
|
881
|
+
private validateIncomingRequest(
|
|
882
|
+
requestContext: GatewayGraphQLRequestContext,
|
|
887
883
|
operationContext: OperationContext,
|
|
888
884
|
) {
|
|
889
885
|
return tracer.startActiveSpan(OpenTelemetrySpanNames.VALIDATE, (span) => {
|
package/src/logger.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import loglevel from 'loglevel';
|
|
2
2
|
import type { Logger } from '@apollo/utils.logger';
|
|
3
3
|
|
|
4
|
-
export function getDefaultLogger(debug: boolean =
|
|
4
|
+
export function getDefaultLogger(debug: boolean = false): Logger {
|
|
5
5
|
const logger = loglevel.getLogger('apollo-gateway');
|
|
6
6
|
|
|
7
7
|
const level = debug === true ? loglevel.levels.DEBUG : loglevel.levels.WARN;
|
|
@@ -3,9 +3,63 @@ import { addExtensions } from '../addExtensions';
|
|
|
3
3
|
const { version } = require('../../../package.json');
|
|
4
4
|
|
|
5
5
|
describe('addExtensions', () => {
|
|
6
|
+
|
|
6
7
|
it('adds gateway extensions to a schema', async () => {
|
|
7
8
|
const schema = buildSchema('type Query { hello: String }');
|
|
8
9
|
expect(schema.extensions).toEqual({});
|
|
9
10
|
expect(addExtensions(schema).extensions).toEqual({ apollo: { gateway: { version: version } } });
|
|
10
11
|
});
|
|
12
|
+
|
|
13
|
+
it('does not delete existing extensions', async () => {
|
|
14
|
+
const schema = buildSchema('type Query { hello: String }');
|
|
15
|
+
expect(schema.extensions).toEqual({});
|
|
16
|
+
schema.extensions = {
|
|
17
|
+
foo: 'bar',
|
|
18
|
+
apollo: {
|
|
19
|
+
gateway: {
|
|
20
|
+
version: 'hello'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
expect(addExtensions(schema).extensions).toEqual({
|
|
25
|
+
foo: 'bar',
|
|
26
|
+
apollo: {
|
|
27
|
+
gateway: {
|
|
28
|
+
version: version
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('works with undefined apollo block', async () => {
|
|
35
|
+
const schema = buildSchema('type Query { hello: String }');
|
|
36
|
+
expect(schema.extensions).toEqual({});
|
|
37
|
+
schema.extensions = {
|
|
38
|
+
apollo: undefined
|
|
39
|
+
};
|
|
40
|
+
expect(addExtensions(schema).extensions).toEqual({
|
|
41
|
+
apollo: {
|
|
42
|
+
gateway: {
|
|
43
|
+
version: version
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('works with undefined gateway block', async () => {
|
|
50
|
+
const schema = buildSchema('type Query { hello: String }');
|
|
51
|
+
expect(schema.extensions).toEqual({});
|
|
52
|
+
schema.extensions = {
|
|
53
|
+
apollo: {
|
|
54
|
+
gateway: undefined
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
expect(addExtensions(schema).extensions).toEqual({
|
|
58
|
+
apollo: {
|
|
59
|
+
gateway: {
|
|
60
|
+
version: version
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
11
65
|
});
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { GraphQLSchema } from 'graphql';
|
|
2
|
+
import { GraphQLSchemaExtensions } from 'graphql/type/schema';
|
|
3
|
+
|
|
2
4
|
const { version } = require('../../package.json');
|
|
3
5
|
|
|
4
6
|
export function addExtensions(schema: GraphQLSchema): GraphQLSchema {
|
|
7
|
+
const schemaExtension = schema.extensions as GraphQLSchemaExtensions ?? {};
|
|
8
|
+
const apolloExtension = schemaExtension?.apollo ?? {};
|
|
9
|
+
const gatewayExtension = apolloExtension?.gateway ?? {};
|
|
10
|
+
|
|
5
11
|
schema.extensions = {
|
|
6
12
|
...schema.extensions,
|
|
7
13
|
apollo: {
|
|
8
|
-
...
|
|
14
|
+
...apolloExtension,
|
|
9
15
|
gateway: {
|
|
10
|
-
...
|
|
16
|
+
...gatewayExtension,
|
|
11
17
|
version,
|
|
12
18
|
}
|
|
13
19
|
},
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { GraphQLRequest } from 'apollo-server-types';
|
|
2
1
|
import { parse } from 'graphql';
|
|
3
2
|
import { Headers, type HeadersInit } from 'node-fetch';
|
|
4
3
|
import { ServiceDefinition } from '@apollo/federation-internals';
|
|
5
4
|
import { GraphQLDataSource, GraphQLDataSourceRequestKind } from '../../datasources/types';
|
|
6
5
|
import { SERVICE_DEFINITION_QUERY } from '../..';
|
|
7
6
|
import { ServiceDefinitionUpdate, ServiceEndpointDefinition } from '../../config';
|
|
7
|
+
import { GatewayGraphQLRequest } from '@apollo/server-gateway-interface';
|
|
8
8
|
|
|
9
9
|
export type Service = ServiceEndpointDefinition & {
|
|
10
10
|
dataSource: GraphQLDataSource;
|
|
@@ -35,7 +35,7 @@ export async function loadServicesFromRemoteEndpoint({
|
|
|
35
35
|
`Tried to load schema for '${name}' but no 'url' was specified.`);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
const request:
|
|
38
|
+
const request: GatewayGraphQLRequest = {
|
|
39
39
|
query: SERVICE_DEFINITION_QUERY,
|
|
40
40
|
http: {
|
|
41
41
|
url,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import nock from 'nock';
|
|
1
2
|
import {
|
|
2
3
|
loadSupergraphSdlFromStorage,
|
|
3
4
|
loadSupergraphSdlFromUplinks,
|
|
@@ -21,6 +22,7 @@ import {
|
|
|
21
22
|
nockAfterEach,
|
|
22
23
|
nockBeforeEach,
|
|
23
24
|
} from '../../../__tests__/nockAssertions';
|
|
25
|
+
import { FetcherRequestInit } from '@apollo/utils.fetcher';
|
|
24
26
|
|
|
25
27
|
const logger = {
|
|
26
28
|
warn: jest.fn(),
|
|
@@ -90,6 +92,48 @@ describe('loadSupergraphSdlFromStorage', () => {
|
|
|
90
92
|
});
|
|
91
93
|
});
|
|
92
94
|
|
|
95
|
+
it('Queries alternate Uplink URL if first one times out', async () => {
|
|
96
|
+
mockSupergraphSdlRequest('originalId-1234', mockCloudConfigUrl1).delay(120_000).reply(500);
|
|
97
|
+
mockSupergraphSdlRequestIfAfter(
|
|
98
|
+
'originalId-1234',
|
|
99
|
+
mockCloudConfigUrl2,
|
|
100
|
+
).reply(
|
|
101
|
+
200,
|
|
102
|
+
JSON.stringify({
|
|
103
|
+
data: {
|
|
104
|
+
routerConfig: {
|
|
105
|
+
__typename: 'RouterConfigResult',
|
|
106
|
+
id: 'originalId-1234',
|
|
107
|
+
supergraphSdl: getTestingSupergraphSdl(),
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
}),
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const result = await loadSupergraphSdlFromUplinks({
|
|
114
|
+
graphRef,
|
|
115
|
+
apiKey,
|
|
116
|
+
endpoints: [mockCloudConfigUrl1, mockCloudConfigUrl2],
|
|
117
|
+
errorReportingEndpoint: undefined,
|
|
118
|
+
fetcher,
|
|
119
|
+
requestTimeoutMs,
|
|
120
|
+
compositionId: 'originalId-1234',
|
|
121
|
+
maxRetries: 1,
|
|
122
|
+
roundRobinSeed: 0,
|
|
123
|
+
logger,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
expect(result).toMatchObject({
|
|
127
|
+
id: 'originalId-1234',
|
|
128
|
+
supergraphSdl: getTestingSupergraphSdl(),
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// We're intentionally delaying the response above, so we need to make sure
|
|
132
|
+
// nock shuts down correctly, and isn't related to the underlying abort
|
|
133
|
+
// mechanism.
|
|
134
|
+
nock.abortPendingRequests();
|
|
135
|
+
});
|
|
136
|
+
|
|
93
137
|
it('Throws error if all Uplink URLs fail', async () => {
|
|
94
138
|
mockSupergraphSdlRequest('originalId-1234', mockCloudConfigUrl1).reply(500);
|
|
95
139
|
mockSupergraphSdlRequestIfAfter(
|
|
@@ -417,9 +461,9 @@ describe('loadSupergraphSdlFromUplinks', () => {
|
|
|
417
461
|
apiKey,
|
|
418
462
|
endpoints: [mockCloudConfigUrl1, mockCloudConfigUrl2],
|
|
419
463
|
errorReportingEndpoint: mockOutOfBandReporterUrl,
|
|
420
|
-
fetcher: (
|
|
464
|
+
fetcher: (url: string, init?: FetcherRequestInit) => {
|
|
421
465
|
calls++;
|
|
422
|
-
return fetcher(
|
|
466
|
+
return fetcher(url, init);
|
|
423
467
|
},
|
|
424
468
|
requestTimeoutMs,
|
|
425
469
|
compositionId: 'id-1234',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as makeFetchHappen from 'make-fetch-happen';
|
|
2
2
|
import type { Logger } from '@apollo/utils.logger';
|
|
3
|
+
import type { Fetcher } from '@apollo/utils.fetcher';
|
|
3
4
|
import resolvable, { Resolvable } from '@josephg/resolvable';
|
|
4
5
|
import { SupergraphManager, SupergraphSdlHookOptions } from '../../config';
|
|
5
6
|
import {
|
|
@@ -8,7 +9,6 @@ import {
|
|
|
8
9
|
} from '../..';
|
|
9
10
|
import { getDefaultLogger } from '../../logger';
|
|
10
11
|
import { loadSupergraphSdlFromUplinks } from './loadSupergraphSdlFromStorage';
|
|
11
|
-
import type { AbortableFetcher } from './types';
|
|
12
12
|
|
|
13
13
|
export type FailureToFetchSupergraphSdlFunctionParams = {
|
|
14
14
|
error: Error;
|
|
@@ -58,7 +58,7 @@ export class UplinkSupergraphManager implements SupergraphManager {
|
|
|
58
58
|
UplinkSupergraphManager.getUplinkEndpoints();
|
|
59
59
|
private apiKey: string;
|
|
60
60
|
private graphRef: string;
|
|
61
|
-
private fetcher:
|
|
61
|
+
private fetcher: Fetcher = makeFetchHappen.defaults();
|
|
62
62
|
private maxRetries: number;
|
|
63
63
|
private requestTimeoutMs: number =
|
|
64
64
|
UplinkSupergraphManager.DEFAULT_REQUEST_TIMEOUT_MS;
|
|
@@ -100,7 +100,7 @@ export class UplinkSupergraphManager implements SupergraphManager {
|
|
|
100
100
|
fallbackPollIntervalInMs?: number;
|
|
101
101
|
maxRetries?: number;
|
|
102
102
|
initialMaxRetries?: number;
|
|
103
|
-
fetcher?:
|
|
103
|
+
fetcher?: Fetcher;
|
|
104
104
|
shouldRunSubgraphHealthcheck?: boolean;
|
|
105
105
|
onFailureToFetchSupergraphSdlDuringInit?: FailureToFetchSupergraphSdlDuringInit;
|
|
106
106
|
onFailureToFetchSupergraphSdlAfterInit?: FailureToFetchSupergraphSdlAfterInit;
|
|
@@ -4,12 +4,12 @@ import { AbortController } from "node-abort-controller";
|
|
|
4
4
|
import { SupergraphSdlUpdate } from '../../config';
|
|
5
5
|
import { submitOutOfBandReportIfConfigured } from './outOfBandReporter';
|
|
6
6
|
import { SupergraphSdlQuery } from '../../__generated__/graphqlTypes';
|
|
7
|
-
import type { FetcherResponse } from '@apollo/utils.fetcher';
|
|
8
|
-
import type { Logger } from '@apollo/utils.logger';
|
|
9
7
|
import type {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
FetcherResponse,
|
|
9
|
+
Fetcher,
|
|
10
|
+
FetcherRequestInit,
|
|
11
|
+
} from '@apollo/utils.fetcher';
|
|
12
|
+
import type { Logger } from '@apollo/utils.logger';
|
|
13
13
|
|
|
14
14
|
// Magic /* GraphQL */ comment below is for codegen, do not remove
|
|
15
15
|
export const SUPERGRAPH_SDL_QUERY = /* GraphQL */`#graphql
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { FetcherResponse } from '@apollo/utils.fetcher';
|
|
1
|
+
import { FetcherResponse, type Fetcher } from '@apollo/utils.fetcher';
|
|
2
2
|
import { GraphQLError } from 'graphql';
|
|
3
3
|
import {
|
|
4
4
|
ErrorCode,
|
|
5
5
|
OobReportMutation,
|
|
6
6
|
OobReportMutationVariables,
|
|
7
7
|
} from '../../__generated__/graphqlTypes';
|
|
8
|
-
import { type AbortableFetcher as Fetcher } from './types';
|
|
9
8
|
|
|
10
9
|
// Magic /* GraphQL */ comment below is for codegen, do not remove
|
|
11
10
|
export const OUT_OF_BAND_REPORTER_QUERY = /* GraphQL */`#graphql
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { AbortSignal } from 'node-abort-controller';
|
|
2
|
-
import type { Fetcher, FetcherRequestInit } from '@apollo/utils.fetcher';
|
|
3
|
-
export interface AbortableFetcherRequestInit extends FetcherRequestInit {
|
|
4
|
-
signal?: AbortSignal | null | undefined;
|
|
5
|
-
}
|
|
6
|
-
export interface AbortableFetcher extends Fetcher {
|
|
7
|
-
init?: AbortableFetcherRequestInit;
|
|
8
|
-
}
|
|
9
|
-
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/supergraphManagers/UplinkSupergraphManager/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEzE,MAAM,WAAW,2BAA4B,SAAQ,kBAAkB;IACrE,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;CACzC;AAED,MAAM,WAAW,gBAAiB,SAAQ,OAAO;IAC/C,IAAI,CAAC,EAAE,2BAA2B,CAAC;CACpC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/supergraphManagers/UplinkSupergraphManager/types.ts"],"names":[],"mappings":";;AAKC,CAAC;AAID,CAAC"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { AbortSignal } from 'node-abort-controller';
|
|
2
|
-
import type { Fetcher, FetcherRequestInit } from '@apollo/utils.fetcher';
|
|
3
|
-
|
|
4
|
-
export interface AbortableFetcherRequestInit extends FetcherRequestInit {
|
|
5
|
-
signal?: AbortSignal | null | undefined;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export interface AbortableFetcher extends Fetcher {
|
|
9
|
-
init?: AbortableFetcherRequestInit;
|
|
10
|
-
};
|