/
AddTypenameToAbstract.ts
64 lines (57 loc) · 1.58 KB
/
AddTypenameToAbstract.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
import {
GraphQLType,
DocumentNode,
TypeInfo,
visit,
visitWithTypeInfo,
SelectionSetNode,
Kind,
GraphQLSchema,
isAbstractType,
} from 'graphql';
import { Request } from '@graphql-tools/utils';
import { Transform, DelegationContext } from '../types';
export default class AddTypenameToAbstract implements Transform {
private readonly targetSchema: GraphQLSchema;
constructor(targetSchema: GraphQLSchema) {
this.targetSchema = targetSchema;
}
public transformRequest(
originalRequest: Request,
_delegationContext: DelegationContext,
_transformationContext: Record<string, any>
): Request {
const document = addTypenameToAbstract(this.targetSchema, originalRequest.document);
return {
...originalRequest,
document,
};
}
}
function addTypenameToAbstract(targetSchema: GraphQLSchema, document: DocumentNode): DocumentNode {
const typeInfo = new TypeInfo(targetSchema);
return visit(
document,
visitWithTypeInfo(typeInfo, {
[Kind.SELECTION_SET](node: SelectionSetNode): SelectionSetNode | null | undefined {
const parentType: GraphQLType = typeInfo.getParentType();
let selections = node.selections;
if (parentType != null && isAbstractType(parentType)) {
selections = selections.concat({
kind: Kind.FIELD,
name: {
kind: Kind.NAME,
value: '__typename',
},
});
}
if (selections !== node.selections) {
return {
...node,
selections,
};
}
},
})
);
}