-
-
Notifications
You must be signed in to change notification settings - Fork 798
/
addSimpleRoutingResolvers.ts
94 lines (83 loc) · 2.45 KB
/
addSimpleRoutingResolvers.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
import { mapValues, isEmpty } from 'lodash';
import {
printSchema,
print,
GraphQLError,
GraphQLFieldResolver,
GraphQLSchema,
GraphQLInterfaceType,
GraphQLUnionType,
OperationDefinitionNode,
} from 'graphql';
import { makeExecutableSchema } from '../schemaGenerator';
import { resolveFromParentTypename } from './resolveFromTypename';
import addTypenameForFragments from './addTypenameForFragments';
type ResolverMap = { [key: string]: GraphQLFieldResolver<any, any> };
export type Fetcher = (
operation: {
query: string;
operationName?: string;
variables?: { [key: string]: any };
},
) => Promise<{ data: { [key: string]: any }; errors: Array<GraphQLError> }>;
export default function addSimpleRoutingResolvers(
schema: GraphQLSchema,
fetcher: Fetcher,
): GraphQLSchema {
const queries = schema.getQueryType().getFields();
const queryResolvers: ResolverMap = mapValues(queries, (field, key) =>
createResolver(fetcher, key, schema),
);
let mutationResolvers: ResolverMap = {};
const mutationType = schema.getMutationType();
if (mutationType) {
const mutations = mutationType.getFields();
mutationResolvers = mapValues(mutations, (field, key) =>
createResolver(fetcher, key, schema),
);
}
const resolvers: {
Query: ResolverMap;
Mutation?: ResolverMap;
} = {
Query: queryResolvers,
};
if (!isEmpty(mutationResolvers)) {
resolvers.Mutation = mutationResolvers;
}
// Add interface and union resolveType functions
const typeMap = schema.getTypeMap();
Object.keys(typeMap).forEach(typeName => {
const type = typeMap[typeName];
if (
type instanceof GraphQLInterfaceType ||
type instanceof GraphQLUnionType
) {
type.resolveType = parent => resolveFromParentTypename(parent, schema);
}
});
return makeExecutableSchema({
typeDefs: printSchema(schema),
resolvers,
});
}
function createResolver(
fetcher: Fetcher,
name: string,
schema: GraphQLSchema,
): GraphQLFieldResolver<any, any> {
return async (root, args, context, info) => {
// Yo this is not going to work with fragments
const newOperation: OperationDefinitionNode = addTypenameForFragments(info.operation, schema);
const query = print(newOperation);
const result = await fetcher({
query,
variables: info.variableValues,
});
if (result.errors || !result.data[name]) {
throw result.errors;
} else {
return result.data[name];
}
};
}