/
loadServicesFromRemoteEndpoint.ts
82 lines (75 loc) 路 2.45 KB
/
loadServicesFromRemoteEndpoint.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import { GraphQLRequest } from 'apollo-server-types';
import { parse } from 'graphql';
import { Headers, HeadersInit } from 'node-fetch';
import { GraphQLDataSource } from './datasources/types';
import { Experimental_UpdateServiceDefinitions } from './';
import { ServiceDefinition } from '@apollo/federation';
export async function getServiceDefinitionsFromRemoteEndpoint({
serviceList,
headers = {},
serviceSdlCache,
}: {
serviceList: {
name: string;
url?: string;
dataSource: GraphQLDataSource;
}[];
headers?: HeadersInit;
serviceSdlCache: Map<string, string>;
}): ReturnType<Experimental_UpdateServiceDefinitions> {
if (!serviceList || !serviceList.length) {
throw new Error(
'Tried to load services from remote endpoints but none provided',
);
}
let isNewSchema = false;
// for each service, fetch its introspection schema
const serviceDefinitions: ServiceDefinition[] = (await Promise.all(
serviceList.map(({ name, url, dataSource }) => {
if (!url) {
throw new Error(`Tried to load schema from ${name} but no url found`);
}
const request: GraphQLRequest = {
query: 'query GetServiceDefinition { _service { sdl } }',
http: {
url,
method: 'POST',
headers: new Headers(headers),
},
};
return dataSource
.process({ request, context: {} })
.then(({ data, errors }) => {
if (data && !errors) {
const typeDefs = data._service.sdl as string;
const previousDefinition = serviceSdlCache.get(name);
// this lets us know if any downstream service has changed
// and we need to recalculate the schema
if (previousDefinition !== typeDefs) {
isNewSchema = true;
}
serviceSdlCache.set(name, typeDefs);
return {
name,
url,
typeDefs: parse(typeDefs),
};
}
// XXX handle local errors better for local development
if (errors) {
errors.forEach(console.error);
}
return false;
})
.catch(error => {
console.warn(
`Encountered error when loading ${name} at ${url}: ${error.message}`,
);
return false;
});
}),
).then(serviceDefinitions =>
serviceDefinitions.filter(Boolean),
)) as ServiceDefinition[];
return { serviceDefinitions, isNewSchema }
}