/
AddSelectionSets.ts
103 lines (89 loc) · 3.29 KB
/
AddSelectionSets.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
import {
GraphQLSchema,
SelectionSetNode,
TypeInfo,
GraphQLOutputType,
Kind,
FieldNode,
SelectionNode,
print,
} from 'graphql';
import { Request } from '@graphql-tools/utils';
import { Transform, DelegationContext } from '../types';
import { memoize2 } from '../memoize';
import VisitSelectionSets from './VisitSelectionSets';
export default class AddSelectionSets implements Transform {
private readonly transformer: VisitSelectionSets;
constructor(
sourceSchema: GraphQLSchema,
initialType: GraphQLOutputType,
selectionSetsByType: Record<string, SelectionSetNode>,
selectionSetsByField: Record<string, Record<string, SelectionSetNode>>,
dynamicSelectionSetsByField: Record<string, Record<string, Array<(node: FieldNode) => SelectionSetNode>>>
) {
this.transformer = new VisitSelectionSets(sourceSchema, initialType, (node, typeInfo) =>
visitSelectionSet(node, typeInfo, selectionSetsByType, selectionSetsByField, dynamicSelectionSetsByField)
);
}
public transformRequest(
originalRequest: Request,
delegationContext: DelegationContext,
transformationContext: Record<string, any>
): Request {
return this.transformer.transformRequest(originalRequest, delegationContext, transformationContext);
}
}
function visitSelectionSet(
node: SelectionSetNode,
typeInfo: TypeInfo,
selectionSetsByType: Record<string, SelectionSetNode>,
selectionSetsByField: Record<string, Record<string, SelectionSetNode>>,
dynamicSelectionSetsByField: Record<string, Record<string, Array<(node: FieldNode) => SelectionSetNode>>>
): SelectionSetNode {
const parentType = typeInfo.getParentType();
const newSelections: Map<string, SelectionNode> = new Map();
if (parentType != null) {
const parentTypeName = parentType.name;
addSelectionsToMap(newSelections, node);
if (parentTypeName in selectionSetsByType) {
const selectionSet = selectionSetsByType[parentTypeName];
addSelectionsToMap(newSelections, selectionSet);
}
if (parentTypeName in selectionSetsByField) {
node.selections.forEach(selection => {
if (selection.kind === Kind.FIELD) {
const name = selection.name.value;
const selectionSet = selectionSetsByField[parentTypeName][name];
if (selectionSet != null) {
addSelectionsToMap(newSelections, selectionSet);
}
}
});
}
if (parentTypeName in dynamicSelectionSetsByField) {
node.selections.forEach(selection => {
if (selection.kind === Kind.FIELD) {
const name = selection.name.value;
const dynamicSelectionSets = dynamicSelectionSetsByField[parentTypeName][name];
if (dynamicSelectionSets != null) {
dynamicSelectionSets.forEach(selectionSetFn => {
const selectionSet = selectionSetFn(selection);
if (selectionSet != null) {
addSelectionsToMap(newSelections, selectionSet);
}
});
}
}
});
}
return {
...node,
selections: Array.from(newSelections.values()),
};
}
}
const addSelectionsToMap = memoize2(function (map: Map<string, SelectionNode>, selectionSet: SelectionSetNode): void {
selectionSet.selections.forEach(selection => {
map.set(print(selection), selection);
});
});