UNPKG

10.8 kBJavaScriptView Raw
1import { visit } from './visitor';
2import { printBlockString } from './blockString';
3/**
4 * Converts an AST into a string, using one set of reasonable
5 * formatting rules.
6 */
7
8export function print(ast) {
9 return visit(ast, {
10 leave: printDocASTReducer
11 });
12} // TODO: provide better type coverage in future
13
14var printDocASTReducer = {
15 Name: function Name(node) {
16 return node.value;
17 },
18 Variable: function Variable(node) {
19 return '$' + node.name;
20 },
21 // Document
22 Document: function Document(node) {
23 return join(node.definitions, '\n\n') + '\n';
24 },
25 OperationDefinition: function OperationDefinition(node) {
26 var op = node.operation;
27 var name = node.name;
28 var varDefs = wrap('(', join(node.variableDefinitions, ', '), ')');
29 var directives = join(node.directives, ' ');
30 var selectionSet = node.selectionSet; // Anonymous queries with no directives or variable definitions can use
31 // the query short form.
32
33 return !name && !directives && !varDefs && op === 'query' ? selectionSet : join([op, join([name, varDefs]), directives, selectionSet], ' ');
34 },
35 VariableDefinition: function VariableDefinition(_ref) {
36 var variable = _ref.variable,
37 type = _ref.type,
38 defaultValue = _ref.defaultValue,
39 directives = _ref.directives;
40 return variable + ': ' + type + wrap(' = ', defaultValue) + wrap(' ', join(directives, ' '));
41 },
42 SelectionSet: function SelectionSet(_ref2) {
43 var selections = _ref2.selections;
44 return block(selections);
45 },
46 Field: function Field(_ref3) {
47 var alias = _ref3.alias,
48 name = _ref3.name,
49 args = _ref3.arguments,
50 directives = _ref3.directives,
51 selectionSet = _ref3.selectionSet;
52 return join([wrap('', alias, ': ') + name + wrap('(', join(args, ', '), ')'), join(directives, ' '), selectionSet], ' ');
53 },
54 Argument: function Argument(_ref4) {
55 var name = _ref4.name,
56 value = _ref4.value;
57 return name + ': ' + value;
58 },
59 // Fragments
60 FragmentSpread: function FragmentSpread(_ref5) {
61 var name = _ref5.name,
62 directives = _ref5.directives;
63 return '...' + name + wrap(' ', join(directives, ' '));
64 },
65 InlineFragment: function InlineFragment(_ref6) {
66 var typeCondition = _ref6.typeCondition,
67 directives = _ref6.directives,
68 selectionSet = _ref6.selectionSet;
69 return join(['...', wrap('on ', typeCondition), join(directives, ' '), selectionSet], ' ');
70 },
71 FragmentDefinition: function FragmentDefinition(_ref7) {
72 var name = _ref7.name,
73 typeCondition = _ref7.typeCondition,
74 variableDefinitions = _ref7.variableDefinitions,
75 directives = _ref7.directives,
76 selectionSet = _ref7.selectionSet;
77 return (// Note: fragment variable definitions are experimental and may be changed
78 // or removed in the future.
79 "fragment ".concat(name).concat(wrap('(', join(variableDefinitions, ', '), ')'), " ") + "on ".concat(typeCondition, " ").concat(wrap('', join(directives, ' '), ' ')) + selectionSet
80 );
81 },
82 // Value
83 IntValue: function IntValue(_ref8) {
84 var value = _ref8.value;
85 return value;
86 },
87 FloatValue: function FloatValue(_ref9) {
88 var value = _ref9.value;
89 return value;
90 },
91 StringValue: function StringValue(_ref10, key) {
92 var value = _ref10.value,
93 isBlockString = _ref10.block;
94 return isBlockString ? printBlockString(value, key === 'description' ? '' : ' ') : JSON.stringify(value);
95 },
96 BooleanValue: function BooleanValue(_ref11) {
97 var value = _ref11.value;
98 return value ? 'true' : 'false';
99 },
100 NullValue: function NullValue() {
101 return 'null';
102 },
103 EnumValue: function EnumValue(_ref12) {
104 var value = _ref12.value;
105 return value;
106 },
107 ListValue: function ListValue(_ref13) {
108 var values = _ref13.values;
109 return '[' + join(values, ', ') + ']';
110 },
111 ObjectValue: function ObjectValue(_ref14) {
112 var fields = _ref14.fields;
113 return '{' + join(fields, ', ') + '}';
114 },
115 ObjectField: function ObjectField(_ref15) {
116 var name = _ref15.name,
117 value = _ref15.value;
118 return name + ': ' + value;
119 },
120 // Directive
121 Directive: function Directive(_ref16) {
122 var name = _ref16.name,
123 args = _ref16.arguments;
124 return '@' + name + wrap('(', join(args, ', '), ')');
125 },
126 // Type
127 NamedType: function NamedType(_ref17) {
128 var name = _ref17.name;
129 return name;
130 },
131 ListType: function ListType(_ref18) {
132 var type = _ref18.type;
133 return '[' + type + ']';
134 },
135 NonNullType: function NonNullType(_ref19) {
136 var type = _ref19.type;
137 return type + '!';
138 },
139 // Type System Definitions
140 SchemaDefinition: function SchemaDefinition(_ref20) {
141 var directives = _ref20.directives,
142 operationTypes = _ref20.operationTypes;
143 return join(['schema', join(directives, ' '), block(operationTypes)], ' ');
144 },
145 OperationTypeDefinition: function OperationTypeDefinition(_ref21) {
146 var operation = _ref21.operation,
147 type = _ref21.type;
148 return operation + ': ' + type;
149 },
150 ScalarTypeDefinition: addDescription(function (_ref22) {
151 var name = _ref22.name,
152 directives = _ref22.directives;
153 return join(['scalar', name, join(directives, ' ')], ' ');
154 }),
155 ObjectTypeDefinition: addDescription(function (_ref23) {
156 var name = _ref23.name,
157 interfaces = _ref23.interfaces,
158 directives = _ref23.directives,
159 fields = _ref23.fields;
160 return join(['type', name, wrap('implements ', join(interfaces, ' & ')), join(directives, ' '), block(fields)], ' ');
161 }),
162 FieldDefinition: addDescription(function (_ref24) {
163 var name = _ref24.name,
164 args = _ref24.arguments,
165 type = _ref24.type,
166 directives = _ref24.directives;
167 return name + (hasMultilineItems(args) ? wrap('(\n', indent(join(args, '\n')), '\n)') : wrap('(', join(args, ', '), ')')) + ': ' + type + wrap(' ', join(directives, ' '));
168 }),
169 InputValueDefinition: addDescription(function (_ref25) {
170 var name = _ref25.name,
171 type = _ref25.type,
172 defaultValue = _ref25.defaultValue,
173 directives = _ref25.directives;
174 return join([name + ': ' + type, wrap('= ', defaultValue), join(directives, ' ')], ' ');
175 }),
176 InterfaceTypeDefinition: addDescription(function (_ref26) {
177 var name = _ref26.name,
178 directives = _ref26.directives,
179 fields = _ref26.fields;
180 return join(['interface', name, join(directives, ' '), block(fields)], ' ');
181 }),
182 UnionTypeDefinition: addDescription(function (_ref27) {
183 var name = _ref27.name,
184 directives = _ref27.directives,
185 types = _ref27.types;
186 return join(['union', name, join(directives, ' '), types && types.length !== 0 ? '= ' + join(types, ' | ') : ''], ' ');
187 }),
188 EnumTypeDefinition: addDescription(function (_ref28) {
189 var name = _ref28.name,
190 directives = _ref28.directives,
191 values = _ref28.values;
192 return join(['enum', name, join(directives, ' '), block(values)], ' ');
193 }),
194 EnumValueDefinition: addDescription(function (_ref29) {
195 var name = _ref29.name,
196 directives = _ref29.directives;
197 return join([name, join(directives, ' ')], ' ');
198 }),
199 InputObjectTypeDefinition: addDescription(function (_ref30) {
200 var name = _ref30.name,
201 directives = _ref30.directives,
202 fields = _ref30.fields;
203 return join(['input', name, join(directives, ' '), block(fields)], ' ');
204 }),
205 DirectiveDefinition: addDescription(function (_ref31) {
206 var name = _ref31.name,
207 args = _ref31.arguments,
208 repeatable = _ref31.repeatable,
209 locations = _ref31.locations;
210 return 'directive @' + name + (hasMultilineItems(args) ? wrap('(\n', indent(join(args, '\n')), '\n)') : wrap('(', join(args, ', '), ')')) + (repeatable ? ' repeatable' : '') + ' on ' + join(locations, ' | ');
211 }),
212 SchemaExtension: function SchemaExtension(_ref32) {
213 var directives = _ref32.directives,
214 operationTypes = _ref32.operationTypes;
215 return join(['extend schema', join(directives, ' '), block(operationTypes)], ' ');
216 },
217 ScalarTypeExtension: function ScalarTypeExtension(_ref33) {
218 var name = _ref33.name,
219 directives = _ref33.directives;
220 return join(['extend scalar', name, join(directives, ' ')], ' ');
221 },
222 ObjectTypeExtension: function ObjectTypeExtension(_ref34) {
223 var name = _ref34.name,
224 interfaces = _ref34.interfaces,
225 directives = _ref34.directives,
226 fields = _ref34.fields;
227 return join(['extend type', name, wrap('implements ', join(interfaces, ' & ')), join(directives, ' '), block(fields)], ' ');
228 },
229 InterfaceTypeExtension: function InterfaceTypeExtension(_ref35) {
230 var name = _ref35.name,
231 directives = _ref35.directives,
232 fields = _ref35.fields;
233 return join(['extend interface', name, join(directives, ' '), block(fields)], ' ');
234 },
235 UnionTypeExtension: function UnionTypeExtension(_ref36) {
236 var name = _ref36.name,
237 directives = _ref36.directives,
238 types = _ref36.types;
239 return join(['extend union', name, join(directives, ' '), types && types.length !== 0 ? '= ' + join(types, ' | ') : ''], ' ');
240 },
241 EnumTypeExtension: function EnumTypeExtension(_ref37) {
242 var name = _ref37.name,
243 directives = _ref37.directives,
244 values = _ref37.values;
245 return join(['extend enum', name, join(directives, ' '), block(values)], ' ');
246 },
247 InputObjectTypeExtension: function InputObjectTypeExtension(_ref38) {
248 var name = _ref38.name,
249 directives = _ref38.directives,
250 fields = _ref38.fields;
251 return join(['extend input', name, join(directives, ' '), block(fields)], ' ');
252 }
253};
254
255function addDescription(cb) {
256 return function (node) {
257 return join([node.description, cb(node)], '\n');
258 };
259}
260/**
261 * Given maybeArray, print an empty string if it is null or empty, otherwise
262 * print all items together separated by separator if provided
263 */
264
265
266function join(maybeArray, separator) {
267 return maybeArray ? maybeArray.filter(function (x) {
268 return x;
269 }).join(separator || '') : '';
270}
271/**
272 * Given array, print each item on its own line, wrapped in an
273 * indented "{ }" block.
274 */
275
276
277function block(array) {
278 return array && array.length !== 0 ? '{\n' + indent(join(array, '\n')) + '\n}' : '';
279}
280/**
281 * If maybeString is not null or empty, then wrap with start and end, otherwise
282 * print an empty string.
283 */
284
285
286function wrap(start, maybeString, end) {
287 return maybeString ? start + maybeString + (end || '') : '';
288}
289
290function indent(maybeString) {
291 return maybeString && ' ' + maybeString.replace(/\n/g, '\n ');
292}
293
294function isMultiline(string) {
295 return string.indexOf('\n') !== -1;
296}
297
298function hasMultilineItems(maybeArray) {
299 return maybeArray && maybeArray.some(isMultiline);
300}