printer.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.print = print;
  6. var _visitor = require("./visitor.js");
  7. var _blockString = require("./blockString.js");
  8. /**
  9. * Converts an AST into a string, using one set of reasonable
  10. * formatting rules.
  11. */
  12. function print(ast) {
  13. return (0, _visitor.visit)(ast, {
  14. leave: printDocASTReducer
  15. });
  16. }
  17. var MAX_LINE_LENGTH = 80; // TODO: provide better type coverage in future
  18. var printDocASTReducer = {
  19. Name: function Name(node) {
  20. return node.value;
  21. },
  22. Variable: function Variable(node) {
  23. return '$' + node.name;
  24. },
  25. // Document
  26. Document: function Document(node) {
  27. return join(node.definitions, '\n\n') + '\n';
  28. },
  29. OperationDefinition: function OperationDefinition(node) {
  30. var op = node.operation;
  31. var name = node.name;
  32. var varDefs = wrap('(', join(node.variableDefinitions, ', '), ')');
  33. var directives = join(node.directives, ' ');
  34. var selectionSet = node.selectionSet; // Anonymous queries with no directives or variable definitions can use
  35. // the query short form.
  36. return !name && !directives && !varDefs && op === 'query' ? selectionSet : join([op, join([name, varDefs]), directives, selectionSet], ' ');
  37. },
  38. VariableDefinition: function VariableDefinition(_ref) {
  39. var variable = _ref.variable,
  40. type = _ref.type,
  41. defaultValue = _ref.defaultValue,
  42. directives = _ref.directives;
  43. return variable + ': ' + type + wrap(' = ', defaultValue) + wrap(' ', join(directives, ' '));
  44. },
  45. SelectionSet: function SelectionSet(_ref2) {
  46. var selections = _ref2.selections;
  47. return block(selections);
  48. },
  49. Field: function Field(_ref3) {
  50. var alias = _ref3.alias,
  51. name = _ref3.name,
  52. args = _ref3.arguments,
  53. directives = _ref3.directives,
  54. selectionSet = _ref3.selectionSet;
  55. var prefix = wrap('', alias, ': ') + name;
  56. var argsLine = prefix + wrap('(', join(args, ', '), ')');
  57. if (argsLine.length > MAX_LINE_LENGTH) {
  58. argsLine = prefix + wrap('(\n', indent(join(args, '\n')), '\n)');
  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 ? (0, _blockString.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. function addDescription(cb) {
  265. return function (node) {
  266. return join([node.description, cb(node)], '\n');
  267. };
  268. }
  269. /**
  270. * Given maybeArray, print an empty string if it is null or empty, otherwise
  271. * print all items together separated by separator if provided
  272. */
  273. function join(maybeArray) {
  274. var _maybeArray$filter$jo;
  275. var separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
  276. return (_maybeArray$filter$jo = maybeArray === null || maybeArray === void 0 ? void 0 : maybeArray.filter(function (x) {
  277. return x;
  278. }).join(separator)) !== null && _maybeArray$filter$jo !== void 0 ? _maybeArray$filter$jo : '';
  279. }
  280. /**
  281. * Given array, print each item on its own line, wrapped in an
  282. * indented "{ }" block.
  283. */
  284. function block(array) {
  285. return wrap('{\n', indent(join(array, '\n')), '\n}');
  286. }
  287. /**
  288. * If maybeString is not null or empty, then wrap with start and end, otherwise print an empty string.
  289. */
  290. function wrap(start, maybeString) {
  291. var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
  292. return maybeString != null && maybeString !== '' ? start + maybeString + end : '';
  293. }
  294. function indent(str) {
  295. return wrap(' ', str.replace(/\n/g, '\n '));
  296. }
  297. function isMultiline(str) {
  298. return str.indexOf('\n') !== -1;
  299. }
  300. function hasMultilineItems(maybeArray) {
  301. return maybeArray != null && maybeArray.some(isMultiline);
  302. }