-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Expand file tree
/
Copy pathtransform.ts
More file actions
86 lines (80 loc) · 2.23 KB
/
Copy pathtransform.ts
File metadata and controls
86 lines (80 loc) · 2.23 KB
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
import type { ASTNode, FieldNode, OperationDefinitionNode } from "graphql";
import { Kind, visit } from "graphql";
const TYPENAME_FIELD: FieldNode = {
kind: Kind.FIELD,
name: {
kind: Kind.NAME,
value: "__typename",
},
};
/**
* Adds `__typename` to all selection sets in the document. The operation
* definition's selection set remains unchanged.
*
* @param doc - The `ASTNode` to add `__typename` to
*
* @example
*
* ```ts
* const document = gql`
* # ...
* `;
*
* const withTypename = addTypenameToDocument(document);
* ```
*/
export const addTypenameToDocument = Object.assign(
function <TNode extends ASTNode>(doc: TNode): TNode {
return visit(doc, {
SelectionSet: {
enter(node, _key, parent) {
// Don't add __typename to OperationDefinitions.
if (
parent &&
(parent as OperationDefinitionNode).kind ===
Kind.OPERATION_DEFINITION
) {
return;
}
// No changes if no selections.
const { selections } = node;
if (!selections) {
return;
}
// If selections already have a __typename, or are part of an
// introspection query, do nothing.
const skip = selections.some((selection) => {
return (
selection.kind === Kind.FIELD &&
(selection.name.value === "__typename" ||
selection.name.value.lastIndexOf("__", 0) === 0)
);
});
if (skip) {
return;
}
// If this SelectionSet is @export-ed as an input variable, it should
// not have a __typename field (see issue #4691).
const field = parent as FieldNode;
if (
field.kind === Kind.FIELD &&
field.directives &&
field.directives.some((d) => d.name.value === "export")
) {
return;
}
// Create and return a new SelectionSet with a __typename Field.
return {
...node,
selections: [...selections, TYPENAME_FIELD],
};
},
},
});
},
{
added(field: FieldNode): boolean {
return field === TYPENAME_FIELD;
},
}
);