graphql 2.0.27 → 2.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install/templates/base_mutation.erb +2 -0
  3. data/lib/generators/graphql/install/templates/mutation_type.erb +2 -0
  4. data/lib/generators/graphql/install_generator.rb +3 -0
  5. data/lib/generators/graphql/templates/base_argument.erb +2 -0
  6. data/lib/generators/graphql/templates/base_connection.erb +2 -0
  7. data/lib/generators/graphql/templates/base_edge.erb +2 -0
  8. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  9. data/lib/generators/graphql/templates/base_field.erb +2 -0
  10. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  11. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  12. data/lib/generators/graphql/templates/base_object.erb +2 -0
  13. data/lib/generators/graphql/templates/base_resolver.erb +6 -0
  14. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  15. data/lib/generators/graphql/templates/base_union.erb +2 -0
  16. data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
  17. data/lib/generators/graphql/templates/loader.erb +2 -0
  18. data/lib/generators/graphql/templates/mutation.erb +2 -0
  19. data/lib/generators/graphql/templates/node_type.erb +2 -0
  20. data/lib/generators/graphql/templates/query_type.erb +2 -0
  21. data/lib/generators/graphql/templates/schema.erb +2 -0
  22. data/lib/graphql/analysis/ast/analyzer.rb +7 -0
  23. data/lib/graphql/analysis/ast/field_usage.rb +32 -7
  24. data/lib/graphql/analysis/ast/query_complexity.rb +80 -128
  25. data/lib/graphql/analysis/ast/query_depth.rb +7 -2
  26. data/lib/graphql/analysis/ast/visitor.rb +2 -2
  27. data/lib/graphql/analysis/ast.rb +21 -11
  28. data/lib/graphql/backtrace/trace.rb +12 -15
  29. data/lib/graphql/coercion_error.rb +1 -9
  30. data/lib/graphql/dataloader/async_dataloader.rb +85 -0
  31. data/lib/graphql/dataloader/source.rb +11 -3
  32. data/lib/graphql/dataloader.rb +109 -142
  33. data/lib/graphql/duration_encoding_error.rb +16 -0
  34. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +170 -0
  35. data/lib/graphql/execution/interpreter/runtime.rb +70 -248
  36. data/lib/graphql/execution/interpreter.rb +91 -157
  37. data/lib/graphql/execution/lookahead.rb +88 -21
  38. data/lib/graphql/introspection/dynamic_fields.rb +1 -1
  39. data/lib/graphql/introspection/entry_points.rb +11 -5
  40. data/lib/graphql/introspection/schema_type.rb +3 -1
  41. data/lib/graphql/language/block_string.rb +34 -18
  42. data/lib/graphql/language/definition_slice.rb +1 -1
  43. data/lib/graphql/language/document_from_schema_definition.rb +37 -37
  44. data/lib/graphql/language/lexer.rb +271 -177
  45. data/lib/graphql/language/nodes.rb +74 -56
  46. data/lib/graphql/language/parser.rb +697 -1986
  47. data/lib/graphql/language/printer.rb +299 -146
  48. data/lib/graphql/language/sanitized_printer.rb +20 -22
  49. data/lib/graphql/language/static_visitor.rb +167 -0
  50. data/lib/graphql/language/visitor.rb +20 -81
  51. data/lib/graphql/language.rb +1 -0
  52. data/lib/graphql/load_application_object_failed_error.rb +5 -1
  53. data/lib/graphql/pagination/array_connection.rb +3 -3
  54. data/lib/graphql/pagination/connection.rb +28 -1
  55. data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
  56. data/lib/graphql/pagination/relation_connection.rb +3 -3
  57. data/lib/graphql/query/context/scoped_context.rb +101 -0
  58. data/lib/graphql/query/context.rb +36 -98
  59. data/lib/graphql/query/null_context.rb +4 -11
  60. data/lib/graphql/query/validation_pipeline.rb +2 -2
  61. data/lib/graphql/query/variables.rb +3 -3
  62. data/lib/graphql/query.rb +13 -22
  63. data/lib/graphql/railtie.rb +9 -6
  64. data/lib/graphql/rake_task.rb +3 -12
  65. data/lib/graphql/schema/argument.rb +6 -1
  66. data/lib/graphql/schema/build_from_definition.rb +0 -11
  67. data/lib/graphql/schema/directive/one_of.rb +12 -0
  68. data/lib/graphql/schema/directive/specified_by.rb +14 -0
  69. data/lib/graphql/schema/directive.rb +1 -1
  70. data/lib/graphql/schema/enum.rb +3 -3
  71. data/lib/graphql/schema/field/connection_extension.rb +1 -15
  72. data/lib/graphql/schema/field/scope_extension.rb +8 -1
  73. data/lib/graphql/schema/field.rb +8 -5
  74. data/lib/graphql/schema/has_single_input_argument.rb +156 -0
  75. data/lib/graphql/schema/input_object.rb +2 -2
  76. data/lib/graphql/schema/interface.rb +10 -10
  77. data/lib/graphql/schema/introspection_system.rb +2 -0
  78. data/lib/graphql/schema/loader.rb +0 -2
  79. data/lib/graphql/schema/member/base_dsl_methods.rb +2 -1
  80. data/lib/graphql/schema/member/has_arguments.rb +61 -38
  81. data/lib/graphql/schema/member/has_fields.rb +8 -5
  82. data/lib/graphql/schema/member/has_interfaces.rb +23 -9
  83. data/lib/graphql/schema/member/scoped.rb +19 -0
  84. data/lib/graphql/schema/member/validates_input.rb +3 -3
  85. data/lib/graphql/schema/object.rb +8 -0
  86. data/lib/graphql/schema/printer.rb +8 -7
  87. data/lib/graphql/schema/relay_classic_mutation.rb +6 -128
  88. data/lib/graphql/schema/resolver.rb +7 -3
  89. data/lib/graphql/schema/scalar.rb +3 -3
  90. data/lib/graphql/schema/subscription.rb +11 -4
  91. data/lib/graphql/schema/union.rb +1 -1
  92. data/lib/graphql/schema/warden.rb +96 -94
  93. data/lib/graphql/schema.rb +219 -72
  94. data/lib/graphql/static_validation/all_rules.rb +1 -1
  95. data/lib/graphql/static_validation/base_visitor.rb +1 -1
  96. data/lib/graphql/static_validation/literal_validator.rb +1 -1
  97. data/lib/graphql/static_validation/rules/fields_will_merge.rb +1 -1
  98. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -1
  99. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +1 -1
  100. data/lib/graphql/static_validation/validation_context.rb +5 -5
  101. data/lib/graphql/static_validation/validator.rb +3 -0
  102. data/lib/graphql/static_validation.rb +0 -1
  103. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +3 -2
  104. data/lib/graphql/subscriptions/event.rb +8 -2
  105. data/lib/graphql/subscriptions.rb +14 -12
  106. data/lib/graphql/testing/helpers.rb +125 -0
  107. data/lib/graphql/testing.rb +2 -0
  108. data/lib/graphql/tracing/appoptics_trace.rb +2 -2
  109. data/lib/graphql/tracing/appoptics_tracing.rb +2 -2
  110. data/lib/graphql/tracing/data_dog_trace.rb +21 -34
  111. data/lib/graphql/tracing/data_dog_tracing.rb +7 -21
  112. data/lib/graphql/tracing/legacy_hooks_trace.rb +74 -0
  113. data/lib/graphql/tracing/platform_tracing.rb +2 -0
  114. data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +3 -1
  115. data/lib/graphql/tracing/sentry_trace.rb +94 -0
  116. data/lib/graphql/tracing/trace.rb +1 -0
  117. data/lib/graphql/tracing.rb +3 -1
  118. data/lib/graphql/types/iso_8601_duration.rb +77 -0
  119. data/lib/graphql/types/relay/connection_behaviors.rb +32 -2
  120. data/lib/graphql/types/relay/edge_behaviors.rb +7 -0
  121. data/lib/graphql/types.rb +1 -0
  122. data/lib/graphql/version.rb +1 -1
  123. data/lib/graphql.rb +3 -3
  124. data/readme.md +12 -2
  125. metadata +33 -25
  126. data/lib/graphql/deprecation.rb +0 -9
  127. data/lib/graphql/filter.rb +0 -59
  128. data/lib/graphql/language/parser.y +0 -560
  129. data/lib/graphql/static_validation/type_stack.rb +0 -216
  130. data/lib/graphql/subscriptions/instrumentation.rb +0 -28
@@ -2,6 +2,32 @@
2
2
  module GraphQL
3
3
  module Language
4
4
  class Printer
5
+ OMISSION = "... (truncated)"
6
+
7
+ class TruncatableBuffer
8
+ class TruncateSizeReached < StandardError; end
9
+
10
+ DEFAULT_INIT_CAPACITY = 500
11
+
12
+ def initialize(truncate_size: nil)
13
+ @out = String.new(capacity: truncate_size || DEFAULT_INIT_CAPACITY)
14
+ @truncate_size = truncate_size
15
+ end
16
+
17
+ def append(other)
18
+ if @truncate_size && (@out.size + other.size) > @truncate_size
19
+ @out << other.slice(0, @truncate_size - @out.size)
20
+ raise(TruncateSizeReached, "Truncate size reached")
21
+ else
22
+ @out << other
23
+ end
24
+ end
25
+
26
+ def to_string
27
+ @out
28
+ end
29
+ end
30
+
5
31
  # Turn an arbitrary AST node back into a string.
6
32
  #
7
33
  # @example Turning a document into a query string
@@ -14,121 +40,179 @@ module GraphQL
14
40
  #
15
41
  # class MyPrinter < GraphQL::Language::Printer
16
42
  # def print_argument(arg)
17
- # "#{arg.name}: <HIDDEN>"
43
+ # print_string("#{arg.name}: <HIDDEN>")
18
44
  # end
19
45
  # end
20
46
  #
21
47
  # MyPrinter.new.print(document)
22
48
  # # => "mutation { pay(creditCard: <HIDDEN>) { success } }"
23
49
  #
24
- #
50
+ # @param node [Nodes::AbstractNode]
25
51
  # @param indent [String] Whitespace to add to the printed node
52
+ # @param truncate_size [Integer, nil] The size to truncate to.
26
53
  # @return [String] Valid GraphQL for `node`
27
- def print(node, indent: "")
54
+ def print(node, indent: "", truncate_size: nil)
55
+ truncate_size = truncate_size ? [truncate_size - OMISSION.size, 0].max : nil
56
+ @out = TruncatableBuffer.new(truncate_size: truncate_size)
28
57
  print_node(node, indent: indent)
58
+ @out.to_string
59
+ rescue TruncatableBuffer::TruncateSizeReached
60
+ @out.to_string << OMISSION
29
61
  end
30
62
 
31
63
  protected
32
64
 
65
+ def print_string(str)
66
+ @out.append(str)
67
+ end
68
+
33
69
  def print_document(document)
34
- document.definitions.map { |d| print_node(d) }.join("\n\n")
70
+ document.definitions.each_with_index do |d, i|
71
+ print_node(d)
72
+ print_string("\n\n") if i < document.definitions.size - 1
73
+ end
35
74
  end
36
75
 
37
76
  def print_argument(argument)
38
- "#{argument.name}: #{print_node(argument.value)}".dup
77
+ print_string(argument.name)
78
+ print_string(": ")
79
+ print_node(argument.value)
80
+ end
81
+
82
+ def print_input_object(input_object)
83
+ print_string("{")
84
+ input_object.arguments.each_with_index do |a, i|
85
+ print_argument(a)
86
+ print_string(", ") if i < input_object.arguments.size - 1
87
+ end
88
+ print_string("}")
39
89
  end
40
90
 
41
91
  def print_directive(directive)
42
- out = "@#{directive.name}".dup
92
+ print_string("@")
93
+ print_string(directive.name)
43
94
 
44
95
  if directive.arguments.any?
45
- out << "(#{directive.arguments.map { |a| print_argument(a) }.join(", ")})"
96
+ print_string("(")
97
+ directive.arguments.each_with_index do |a, i|
98
+ print_argument(a)
99
+ print_string(", ") if i < directive.arguments.size - 1
100
+ end
101
+ print_string(")")
46
102
  end
47
-
48
- out
49
103
  end
50
104
 
51
105
  def print_enum(enum)
52
- "#{enum.name}".dup
106
+ print_string(enum.name)
53
107
  end
54
108
 
55
109
  def print_null_value
56
- "null".dup
110
+ print_string("null")
57
111
  end
58
112
 
59
113
  def print_field(field, indent: "")
60
- out = "#{indent}".dup
61
- out << "#{field.alias}: " if field.alias
62
- out << "#{field.name}"
63
- out << "(#{field.arguments.map { |a| print_argument(a) }.join(", ")})" if field.arguments.any?
64
- out << print_directives(field.directives)
65
- out << print_selections(field.selections, indent: indent)
66
- out
114
+ print_string(indent)
115
+ if field.alias
116
+ print_string(field.alias)
117
+ print_string(": ")
118
+ end
119
+ print_string(field.name)
120
+ if field.arguments.any?
121
+ print_string("(")
122
+ field.arguments.each_with_index do |a, i|
123
+ print_argument(a)
124
+ print_string(", ") if i < field.arguments.size - 1
125
+ end
126
+ print_string(")")
127
+ end
128
+ print_directives(field.directives)
129
+ print_selections(field.selections, indent: indent)
67
130
  end
68
131
 
69
132
  def print_fragment_definition(fragment_def, indent: "")
70
- out = "#{indent}fragment #{fragment_def.name}".dup
133
+ print_string(indent)
134
+ print_string("fragment")
135
+ if fragment_def.name
136
+ print_string(" ")
137
+ print_string(fragment_def.name)
138
+ end
139
+
71
140
  if fragment_def.type
72
- out << " on #{print_node(fragment_def.type)}"
141
+ print_string(" on ")
142
+ print_node(fragment_def.type)
73
143
  end
74
- out << print_directives(fragment_def.directives)
75
- out << print_selections(fragment_def.selections, indent: indent)
76
- out
144
+ print_directives(fragment_def.directives)
145
+ print_selections(fragment_def.selections, indent: indent)
77
146
  end
78
147
 
79
148
  def print_fragment_spread(fragment_spread, indent: "")
80
- out = "#{indent}...#{fragment_spread.name}".dup
81
- out << print_directives(fragment_spread.directives)
82
- out
149
+ print_string(indent)
150
+ print_string("...")
151
+ print_string(fragment_spread.name)
152
+ print_directives(fragment_spread.directives)
83
153
  end
84
154
 
85
155
  def print_inline_fragment(inline_fragment, indent: "")
86
- out = "#{indent}...".dup
156
+ print_string(indent)
157
+ print_string("...")
87
158
  if inline_fragment.type
88
- out << " on #{print_node(inline_fragment.type)}"
159
+ print_string(" on ")
160
+ print_node(inline_fragment.type)
89
161
  end
90
- out << print_directives(inline_fragment.directives)
91
- out << print_selections(inline_fragment.selections, indent: indent)
92
- out
93
- end
94
-
95
- def print_input_object(input_object)
96
- "{#{input_object.arguments.map { |a| print_argument(a) }.join(", ")}}"
162
+ print_directives(inline_fragment.directives)
163
+ print_selections(inline_fragment.selections, indent: indent)
97
164
  end
98
165
 
99
166
  def print_list_type(list_type)
100
- "[#{print_node(list_type.of_type)}]".dup
167
+ print_string("[")
168
+ print_node(list_type.of_type)
169
+ print_string("]")
101
170
  end
102
171
 
103
172
  def print_non_null_type(non_null_type)
104
- "#{print_node(non_null_type.of_type)}!".dup
173
+ print_node(non_null_type.of_type)
174
+ print_string("!")
105
175
  end
106
176
 
107
177
  def print_operation_definition(operation_definition, indent: "")
108
- out = "#{indent}#{operation_definition.operation_type}".dup
109
- out << " #{operation_definition.name}" if operation_definition.name
178
+ print_string(indent)
179
+ print_string(operation_definition.operation_type)
180
+ if operation_definition.name
181
+ print_string(" ")
182
+ print_string(operation_definition.name)
183
+ end
110
184
 
111
185
  if operation_definition.variables.any?
112
- out << "(#{operation_definition.variables.map { |v| print_variable_definition(v) }.join(", ")})"
186
+ print_string("(")
187
+ operation_definition.variables.each_with_index do |v, i|
188
+ print_variable_definition(v)
189
+ print_string(", ") if i < operation_definition.variables.size - 1
190
+ end
191
+ print_string(")")
113
192
  end
114
193
 
115
- out << print_directives(operation_definition.directives)
116
- out << print_selections(operation_definition.selections, indent: indent)
117
- out
194
+ print_directives(operation_definition.directives)
195
+ print_selections(operation_definition.selections, indent: indent)
118
196
  end
119
197
 
120
198
  def print_type_name(type_name)
121
- "#{type_name.name}".dup
199
+ print_string(type_name.name)
122
200
  end
123
201
 
124
202
  def print_variable_definition(variable_definition)
125
- out = "$#{variable_definition.name}: #{print_node(variable_definition.type)}".dup
126
- out << " = #{print_node(variable_definition.default_value)}" unless variable_definition.default_value.nil?
127
- out
203
+ print_string("$")
204
+ print_string(variable_definition.name)
205
+ print_string(": ")
206
+ print_node(variable_definition.type)
207
+ unless variable_definition.default_value.nil?
208
+ print_string(" = ")
209
+ print_node(variable_definition.default_value)
210
+ end
128
211
  end
129
212
 
130
213
  def print_variable_identifier(variable_identifier)
131
- "$#{variable_identifier.name}".dup
214
+ print_string("$")
215
+ print_string(variable_identifier.name)
132
216
  end
133
217
 
134
218
  def print_schema_definition(schema, extension: false)
@@ -140,175 +224,236 @@ module GraphQL
140
224
  return
141
225
  end
142
226
 
143
- out = extension ? "extend schema".dup : "schema".dup
227
+ extension ? print_string("extend schema") : print_string("schema")
228
+
144
229
  if schema.directives.any?
145
230
  schema.directives.each do |dir|
146
- out << "\n "
147
- out << print_node(dir)
231
+ print_string("\n ")
232
+ print_node(dir)
148
233
  end
234
+
149
235
  if !has_conventional_names
150
- out << "\n"
236
+ print_string("\n")
151
237
  end
152
238
  end
153
239
 
154
240
  if !has_conventional_names
155
241
  if schema.directives.empty?
156
- out << " "
242
+ print_string(" ")
157
243
  end
158
- out << "{\n"
159
- out << " query: #{schema.query}\n" if schema.query
160
- out << " mutation: #{schema.mutation}\n" if schema.mutation
161
- out << " subscription: #{schema.subscription}\n" if schema.subscription
162
- out << "}"
244
+ print_string("{\n")
245
+ print_string(" query: #{schema.query}\n") if schema.query
246
+ print_string(" mutation: #{schema.mutation}\n") if schema.mutation
247
+ print_string(" subscription: #{schema.subscription}\n") if schema.subscription
248
+ print_string("}")
163
249
  end
164
- out
165
250
  end
166
251
 
252
+
167
253
  def print_scalar_type_definition(scalar_type, extension: false)
168
- out = extension ? "extend ".dup : print_description(scalar_type)
169
- out << "scalar #{scalar_type.name}"
170
- out << print_directives(scalar_type.directives)
254
+ extension ? print_string("extend ") : print_description(scalar_type)
255
+ print_string("scalar ")
256
+ print_string(scalar_type.name)
257
+ print_directives(scalar_type.directives)
171
258
  end
172
259
 
173
260
  def print_object_type_definition(object_type, extension: false)
174
- out = extension ? "extend ".dup : print_description(object_type)
175
- out << "type #{object_type.name}"
176
- out << print_implements(object_type) unless object_type.interfaces.empty?
177
- out << print_directives(object_type.directives)
178
- out << print_field_definitions(object_type.fields)
261
+ extension ? print_string("extend ") : print_description(object_type)
262
+ print_string("type ")
263
+ print_string(object_type.name)
264
+ print_implements(object_type) unless object_type.interfaces.empty?
265
+ print_directives(object_type.directives)
266
+ print_field_definitions(object_type.fields)
179
267
  end
180
268
 
181
269
  def print_implements(type)
182
- " implements #{type.interfaces.map(&:name).join(" & ")}"
270
+ print_string(" implements ")
271
+ i = 0
272
+ type.interfaces.each do |int|
273
+ if i > 0
274
+ print_string(" & ")
275
+ end
276
+ print_string(int.name)
277
+ i += 1
278
+ end
183
279
  end
184
280
 
185
281
  def print_input_value_definition(input_value)
186
- out = "#{input_value.name}: #{print_node(input_value.type)}".dup
187
- out << " = #{print_node(input_value.default_value)}" unless input_value.default_value.nil?
188
- out << print_directives(input_value.directives)
282
+ print_string(input_value.name)
283
+ print_string(": ")
284
+ print_node(input_value.type)
285
+ unless input_value.default_value.nil?
286
+ print_string(" = ")
287
+ print_node(input_value.default_value)
288
+ end
289
+ print_directives(input_value.directives)
189
290
  end
190
291
 
191
292
  def print_arguments(arguments, indent: "")
192
- if arguments.all?{ |arg| !arg.description }
193
- return "(#{arguments.map{ |arg| print_input_value_definition(arg) }.join(", ")})"
293
+ if arguments.all? { |arg| !arg.description }
294
+ print_string("(")
295
+ arguments.each_with_index do |arg, i|
296
+ print_input_value_definition(arg)
297
+ print_string(", ") if i < arguments.size - 1
298
+ end
299
+ print_string(")")
300
+ return
194
301
  end
195
302
 
196
- out = "(\n".dup
197
- out << arguments.map.with_index{ |arg, i|
198
- "#{print_description(arg, indent: " " + indent, first_in_block: i == 0)} #{indent}"\
199
- "#{print_input_value_definition(arg)}"
200
- }.join("\n")
201
- out << "\n#{indent})"
303
+ print_string("(\n")
304
+ arguments.each_with_index do |arg, i|
305
+ print_description(arg, indent: " " + indent, first_in_block: i == 0)
306
+ print_string(" ")
307
+ print_string(indent)
308
+ print_input_value_definition(arg)
309
+ print_string("\n") if i < arguments.size - 1
310
+ end
311
+ print_string("\n")
312
+ print_string(indent)
313
+ print_string(")")
202
314
  end
203
315
 
204
316
  def print_field_definition(field)
205
- out = field.name.dup
317
+ print_string(field.name)
206
318
  unless field.arguments.empty?
207
- out << print_arguments(field.arguments, indent: " ")
319
+ print_arguments(field.arguments, indent: " ")
208
320
  end
209
- out << ": #{print_node(field.type)}"
210
- out << print_directives(field.directives)
321
+ print_string(": ")
322
+ print_node(field.type)
323
+ print_directives(field.directives)
211
324
  end
212
325
 
213
326
  def print_interface_type_definition(interface_type, extension: false)
214
- out = extension ? "extend ".dup : print_description(interface_type)
215
- out << "interface #{interface_type.name}"
216
- out << print_implements(interface_type) if interface_type.interfaces.any?
217
- out << print_directives(interface_type.directives)
218
- out << print_field_definitions(interface_type.fields)
327
+ extension ? print_string("extend ") : print_description(interface_type)
328
+ print_string("interface ")
329
+ print_string(interface_type.name)
330
+ print_implements(interface_type) if interface_type.interfaces.any?
331
+ print_directives(interface_type.directives)
332
+ print_field_definitions(interface_type.fields)
219
333
  end
220
334
 
221
335
  def print_union_type_definition(union_type, extension: false)
222
- out = extension ? "extend ".dup : print_description(union_type)
223
- out << "union #{union_type.name}"
224
- out << print_directives(union_type.directives)
225
- out << " = " + union_type.types.map(&:name).join(" | ")
336
+ extension ? print_string("extend ") : print_description(union_type)
337
+ print_string("union ")
338
+ print_string(union_type.name)
339
+ print_directives(union_type.directives)
340
+ if union_type.types.any?
341
+ print_string(" = ")
342
+ i = 0
343
+ union_type.types.each do |t|
344
+ if i > 0
345
+ print_string(" | ")
346
+ end
347
+ print_string(t.name)
348
+ i += 1
349
+ end
350
+ end
226
351
  end
227
352
 
228
353
  def print_enum_type_definition(enum_type, extension: false)
229
- out = extension ? "extend ".dup : print_description(enum_type)
230
- out << "enum #{enum_type.name}#{print_directives(enum_type.directives)} {\n"
231
- enum_type.values.each.with_index do |value, i|
232
- out << print_description(value, indent: ' ', first_in_block: i == 0)
233
- out << print_enum_value_definition(value)
354
+ extension ? print_string("extend ") : print_description(enum_type)
355
+ print_string("enum ")
356
+ print_string(enum_type.name)
357
+ print_directives(enum_type.directives)
358
+ if enum_type.values.any?
359
+ print_string(" {\n")
360
+ enum_type.values.each.with_index do |value, i|
361
+ print_description(value, indent: " ", first_in_block: i == 0)
362
+ print_enum_value_definition(value)
363
+ end
364
+ print_string("}")
234
365
  end
235
- out << "}"
236
366
  end
237
367
 
238
368
  def print_enum_value_definition(enum_value)
239
- out = " #{enum_value.name}".dup
240
- out << print_directives(enum_value.directives)
241
- out << "\n"
369
+ print_string(" ")
370
+ print_string(enum_value.name)
371
+ print_directives(enum_value.directives)
372
+ print_string("\n")
242
373
  end
243
374
 
244
375
  def print_input_object_type_definition(input_object_type, extension: false)
245
- out = extension ? "extend ".dup : print_description(input_object_type)
246
- out << "input #{input_object_type.name}"
247
- out << print_directives(input_object_type.directives)
376
+ extension ? print_string("extend ") : print_description(input_object_type)
377
+ print_string("input ")
378
+ print_string(input_object_type.name)
379
+ print_directives(input_object_type.directives)
248
380
  if !input_object_type.fields.empty?
249
- out << " {\n"
381
+ print_string(" {\n")
250
382
  input_object_type.fields.each.with_index do |field, i|
251
- out << print_description(field, indent: ' ', first_in_block: i == 0)
252
- out << " #{print_input_value_definition(field)}\n"
383
+ print_description(field, indent: " ", first_in_block: i == 0)
384
+ print_string(" ")
385
+ print_input_value_definition(field)
386
+ print_string("\n")
253
387
  end
254
- out << "}"
388
+ print_string("}")
255
389
  end
256
- out
257
390
  end
258
391
 
259
392
  def print_directive_definition(directive)
260
- out = print_description(directive)
261
- out << "directive @#{directive.name}"
393
+ print_description(directive)
394
+ print_string("directive @")
395
+ print_string(directive.name)
262
396
 
263
397
  if directive.arguments.any?
264
- out << print_arguments(directive.arguments)
398
+ print_arguments(directive.arguments)
265
399
  end
266
400
 
267
401
  if directive.repeatable
268
- out << " repeatable"
402
+ print_string(" repeatable")
269
403
  end
270
404
 
271
- out << " on #{directive.locations.map(&:name).join(' | ')}"
405
+ print_string(" on ")
406
+ i = 0
407
+ directive.locations.each do |loc|
408
+ if i > 0
409
+ print_string(" | ")
410
+ end
411
+ print_string(loc.name)
412
+ i += 1
413
+ end
272
414
  end
273
415
 
274
416
  def print_description(node, indent: "", first_in_block: true)
275
- return ''.dup unless node.description
417
+ return unless node.description
276
418
 
277
- description = indent != '' && !first_in_block ? "\n".dup : "".dup
278
- description << GraphQL::Language::BlockString.print(node.description, indent: indent)
419
+ print_string("\n") if indent != "" && !first_in_block
420
+ print_string(GraphQL::Language::BlockString.print(node.description, indent: indent))
279
421
  end
280
422
 
281
423
  def print_field_definitions(fields)
282
- if fields.empty?
283
- ""
284
- else
285
- out = " {\n".dup
286
- fields.each.with_index do |field, i|
287
- out << print_description(field, indent: ' ', first_in_block: i == 0)
288
- out << " #{print_field_definition(field)}\n"
289
- end
290
- out << "}"
424
+ return if fields.empty?
425
+
426
+ print_string(" {\n")
427
+ i = 0
428
+ fields.each do |field|
429
+ print_description(field, indent: " ", first_in_block: i == 0)
430
+ print_string(" ")
431
+ print_field_definition(field)
432
+ print_string("\n")
433
+ i += 1
291
434
  end
435
+ print_string("}")
292
436
  end
293
437
 
294
438
  def print_directives(directives)
295
- if directives.any?
296
- directives.map { |d| " #{print_directive(d)}" }.join
297
- else
298
- ""
439
+ return if directives.empty?
440
+
441
+ directives.each do |d|
442
+ print_string(" ")
443
+ print_directive(d)
299
444
  end
300
445
  end
301
446
 
302
447
  def print_selections(selections, indent: "")
303
- if selections.any?
304
- out = " {\n".dup
305
- selections.each do |selection|
306
- out << print_node(selection, indent: indent + " ") << "\n"
307
- end
308
- out << "#{indent}}"
309
- else
310
- ""
448
+ return if selections.empty?
449
+
450
+ print_string(" {\n")
451
+ selections.each do |selection|
452
+ print_node(selection, indent: indent + " ")
453
+ print_string("\n")
311
454
  end
455
+ print_string(indent)
456
+ print_string("}")
312
457
  end
313
458
 
314
459
  def print_node(node, indent: "")
@@ -382,19 +527,27 @@ module GraphQL
382
527
  when Nodes::DirectiveDefinition
383
528
  print_directive_definition(node)
384
529
  when FalseClass, Float, Integer, NilClass, String, TrueClass, Symbol
385
- GraphQL::Language.serialize(node)
530
+ print_string(GraphQL::Language.serialize(node))
386
531
  when Array
387
- "[#{node.map { |v| print_node(v) }.join(", ")}]".dup
532
+ print_string("[")
533
+ node.each_with_index do |v, i|
534
+ print_node(v)
535
+ print_string(", ") if i < node.length - 1
536
+ end
537
+ print_string("]")
388
538
  when Hash
389
- "{#{node.map { |k, v| "#{k}: #{print_node(v)}" }.join(", ")}}".dup
539
+ print_string("{")
540
+ node.each_with_index do |(k, v), i|
541
+ print_string(k)
542
+ print_string(": ")
543
+ print_node(v)
544
+ print_string(", ") if i < node.length - 1
545
+ end
546
+ print_string("}")
390
547
  else
391
- GraphQL::Language.serialize(node.to_s)
548
+ print_string(GraphQL::Language.serialize(node.to_s))
392
549
  end
393
550
  end
394
-
395
- private
396
-
397
- attr_reader :node
398
551
  end
399
552
  end
400
553
  end