Mirror: The spec-compliant minimum of client-side GraphQL.
1import { Kind } from './kind';
2import { ASTNode } from './ast';
3
4export function printString(string: string) {
5 return JSON.stringify(string);
6}
7
8export function printBlockString(string: string) {
9 return '"""\n' + string.replace(/"""/g, '\\"""') + '\n"""';
10}
11
12const hasItems = <T>(
13 array: ReadonlyArray<T> | undefined | null
14): array is ReadonlyArray<T> => !!(array && array.length);
15
16export function print(node: ASTNode): string {
17 let out: string;
18 switch (node.kind) {
19 case Kind.OPERATION_DEFINITION:
20 if (node.operation === 'query' && !node.name && !hasItems(node.variableDefinitions) && !hasItems(node.directives)) {
21 return print(node.selectionSet);
22 }
23 out = node.operation;
24 if (node.name)
25 out += ' ' + node.name.value;
26 if (hasItems(node.variableDefinitions)) {
27 if (!node.name) out += ' ';
28 out += '(' + node.variableDefinitions.map(print).join(', ') + ')';
29 }
30 if (hasItems(node.directives))
31 out += ' ' + node.directives.map(print).join(' ');
32 return out + ' ' + print(node.selectionSet);
33
34 case Kind.VARIABLE_DEFINITION:
35 out = print(node.variable) +
36 ': ' +
37 print(node.type);
38 if (node.defaultValue)
39 out += ' = ' + print(node.defaultValue);
40 if (hasItems(node.directives))
41 out += ' ' + node.directives.map(print).join(' ');
42 return out;
43
44 case Kind.FIELD:
45 out = (node.alias ? print(node.alias) + ': ' : '') + node.name.value
46 if (hasItems(node.arguments))
47 out += '(' + node.arguments.map(print).join(', ') + ')';
48 if (hasItems(node.directives))
49 out += ' ' + node.directives.map(print).join(' ');
50 return node.selectionSet
51 ? out + ' ' + print(node.selectionSet)
52 : out;
53
54 case Kind.STRING:
55 return node.block
56 ? printBlockString(node.value)
57 : printString(node.value);
58
59 case Kind.BOOLEAN:
60 return '' + node.value;
61
62 case Kind.NULL:
63 return 'null';
64
65 case Kind.INT:
66 case Kind.FLOAT:
67 case Kind.ENUM:
68 case Kind.NAME:
69 return node.value;
70
71 case Kind.LIST:
72 return '[' + node.values.map(print).join(', ') + ']';
73
74 case Kind.OBJECT:
75 return '{' + node.fields.map(print).join(', ') + '}';
76
77 case Kind.OBJECT_FIELD:
78 return node.name.value + ': ' + print(node.value);
79
80 case Kind.VARIABLE:
81 return '$' + node.name.value;
82
83 case Kind.DOCUMENT:
84 return hasItems(node.definitions)
85 ? node.definitions.map(print).join('\n\n')
86 : '';
87
88 case Kind.SELECTION_SET:
89 return '{\n ' +
90 node.selections.map(print).join('\n').replace(/\n/g, '\n ') +
91 '\n}';
92
93 case Kind.ARGUMENT:
94 return node.name.value + ': ' + print(node.value);
95
96 case Kind.FRAGMENT_SPREAD:
97 out = '...' + node.name.value;
98 if (hasItems(node.directives))
99 out += ' ' + node.directives.map(print).join(' ');
100 return out;
101
102 case Kind.INLINE_FRAGMENT:
103 out = '...';
104 if (node.typeCondition)
105 out += ' on ' + node.typeCondition.name.value;
106 if (hasItems(node.directives))
107 out += ' ' + node.directives.map(print).join(' ');
108 return out + ' ' + print(node.selectionSet);
109
110 case Kind.FRAGMENT_DEFINITION:
111 out = 'fragment ' + node.name.value;
112 out += ' on ' + node.typeCondition.name.value;
113 if (hasItems(node.directives))
114 out += ' ' + node.directives.map(print).join(' ');
115 return out + ' ' + print(node.selectionSet);
116
117 case Kind.DIRECTIVE:
118 out = '@' + node.name.value;
119 if (hasItems(node.arguments))
120 out += '(' + node.arguments.map(print).join(', ') + ')';
121 return out;
122
123 case Kind.NAMED_TYPE:
124 return node.name.value;
125
126 case Kind.LIST_TYPE:
127 return '[' + print(node.type) + ']';
128
129 case Kind.NON_NULL_TYPE:
130 return print(node.type) + '!';
131 }
132}