-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGqlParserTreeToGql.ts
117 lines (113 loc) · 3.91 KB
/
GqlParserTreeToGql.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
113
114
115
116
117
import { parseGql } from '@/GqlParser';
import { getValueAsGqlStringNode } from '@/GqlParser/valueNode';
import { Instances, TypeSystemDefinition } from '@/Models';
import { GqlParserTree, VariableDefinitionWithoutLoc } from '@/Models/GqlParserTree';
import { compileType } from '@/shared';
import { Kind } from 'graphql';
export const parseGqlTree = (mainTree: GqlParserTree) => {
const generateName = (tree: GqlParserTree): string => {
if (tree.operation) {
return `${tree.operation}${tree.name ? ` ${tree.name}` : ''}${generateVariableDefinitions(tree)}`;
}
if (tree.fragment) {
return `fragment ${tree.name} on ${tree.node.name}`;
}
if (tree.fragmentSpread) {
return `...${tree.name}`;
}
if (tree.inlineFragment) {
return `...${tree.name ? ` on ${tree.name}` : ''}`;
}
return tree.name || '';
};
const generateChildren = (tree: GqlParserTree): string => {
return `${tree.children?.length ? `{\n ${tree.children.map(generateGql).join('\n ')}\n}` : ''}`;
};
const generateValue = (tree: GqlParserTree): string => {
return `${tree.value ? `: ${getValueAsGqlStringNode(tree.value)}` : ''}`;
};
const generateArguments = (tree: GqlParserTree): string => {
return `${tree.arguments?.length ? `(\n ${tree.arguments.map((a) => generateGql(a)).join(', ')})` : ''}`;
};
const generateGql = (tree: GqlParserTree): string => {
return `${generateName(tree)}${generateValue(tree)}${generateArguments(tree)}${generateChildren(tree)}`;
};
const generateVariableDefinitions = (tree: GqlParserTree): string => {
return `${
tree.variableDefinitions?.length
? `(${tree.variableDefinitions.map((tvd) => `$${tvd.name}: ${tvd.type}`).join(', ')})`
: ''
}`;
};
return generateGql(mainTree);
};
export const parseGqlTrees = (trees: GqlParserTree[]) => {
return trees.map(parseGqlTree).join('\n');
};
export const enrichFieldNodeWithVariables = (
fieldTree: GqlParserTree,
variableDefinitionsUpdate: (
fn: (variableDefinitions: VariableDefinitionWithoutLoc[]) => VariableDefinitionWithoutLoc[],
) => void,
): GqlParserTree => {
if (
fieldTree.node.data.type === TypeSystemDefinition.FieldDefinition ||
fieldTree.node.data.type === Instances.Directive
) {
return {
...fieldTree,
...(fieldTree.node.args.length
? {
arguments: fieldTree.node.args.map((a) => {
const VarName = `${fieldTree.name}_${a.name}`;
const VarNode: GqlParserTree = {
name: a.name,
node: a,
value: {
kind: Kind.VARIABLE,
value: VarName,
},
};
variableDefinitionsUpdate((variableDefinitions) => [
...variableDefinitions,
{
name: VarName,
type: compileType(a.type.fieldType),
},
]);
return VarNode;
}),
}
: {}),
};
}
return fieldTree;
};
export const enrichWholeTreeWithVars = (mainTree: GqlParserTree): GqlParserTree => {
let variableDefinitions: VariableDefinitionWithoutLoc[] = [];
const recursiveEnrich = (tree: GqlParserTree): GqlParserTree => {
return enrichFieldNodeWithVariables(
{
...tree,
...(tree.children
? {
children: tree.children.map(recursiveEnrich),
}
: {}),
...(tree.directives
? {
directives: tree.directives.map(recursiveEnrich),
}
: {}),
},
(varsUpdate) => {
variableDefinitions = varsUpdate(variableDefinitions);
},
);
};
return { ...recursiveEnrich(mainTree), variableDefinitions };
};
export const enrichGqlQueryWithAllVars = (query: string, schema: string) => {
const trees = parseGql(query, schema);
return parseGqlTrees(trees.map(enrichWholeTreeWithVars));
};