forked from profusion/apollo-validation-directives
-
Notifications
You must be signed in to change notification settings - Fork 0
/
federation.ts
112 lines (104 loc) · 2.79 KB
/
federation.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import { GraphQLSchema, DocumentNode, GraphQLFieldResolver } from 'graphql';
import { ApolloServer, SchemaDirectiveVisitor, gql } from 'apollo-server';
import { ApolloGateway } from '@apollo/gateway';
import { buildFederatedSchema } from '@apollo/federation';
import { GraphQLResolverMap } from 'apollo-graphql';
import { ValidateDirectiveVisitor, range, stringLength } from '../lib';
/*
When using apollo federation all
directives should be available to all
federated nodes.
*/
const directives = {
range,
stringLength,
};
const buildSchema = (
resolvers: GraphQLResolverMap<{}>,
typeDefs: DocumentNode,
): GraphQLSchema => {
const finalTypeDefs = [
typeDefs,
...ValidateDirectiveVisitor.getMissingCommonTypeDefs(),
...Object.values(directives).reduce<DocumentNode[]>(
(acc, d) => acc.concat(d.getTypeDefs()),
[],
),
];
const schema = buildFederatedSchema({ resolvers, typeDefs: finalTypeDefs });
SchemaDirectiveVisitor.visitSchemaDirectives(schema, directives);
ValidateDirectiveVisitor.addValidationResolversToSchema(schema);
return schema;
};
interface ServicesSetup {
port: number;
resolvers: {
[typeName: string]: {
[fieldName: string]: GraphQLFieldResolver<unknown, {}>;
};
};
typeDefs: DocumentNode;
}
const services: ServicesSetup[] = [
{
port: 4001,
resolvers: {
Query: {
myNumber: (_: unknown, { args }): number => args,
},
},
typeDefs: gql`
type Query {
myNumber(args: Int @range(max: 100, policy: THROW)): Int
@range(min: 2, policy: THROW)
}
`,
},
{
port: 4002,
resolvers: {
Query: {
myString: (_: unknown, { args }): string => args,
},
},
typeDefs: gql`
type Query {
myString(args: String @stringLength(max: 200, policy: THROW)): String
@stringLength(min: 3, policy: THROW)
}
`,
},
];
const start = async (): Promise<void> => {
const runningString = await Promise.all(
services.map(({ resolvers, typeDefs, port }) =>
new ApolloServer({
schema: buildSchema(resolvers, typeDefs),
}).listen({ port }),
),
);
// eslint-disable-next-line no-console
console.log(runningString.map(({ url }) => url).join('\n'));
const apolloGateway = new ApolloGateway({
serviceList: [
{
name: 'string-service',
url: 'http://localhost:4002',
},
{
name: 'number-service',
url: 'http://localhost:4001',
},
],
});
const server = new ApolloServer({
engine: false,
gateway: apolloGateway,
subscriptions: false,
});
const { url } = await server.listen();
// eslint-disable-next-line no-console
console.log(`🚀 Server ready at ${url}`);
};
// eslint-disable-next-line no-console
start().catch(console.error);