UNPKG

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