graphql 2.0.28 → 2.2.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) 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/request.rb +5 -0
  32. data/lib/graphql/dataloader/source.rb +11 -3
  33. data/lib/graphql/dataloader.rb +109 -142
  34. data/lib/graphql/duration_encoding_error.rb +16 -0
  35. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +170 -0
  36. data/lib/graphql/execution/interpreter/runtime.rb +79 -248
  37. data/lib/graphql/execution/interpreter.rb +91 -157
  38. data/lib/graphql/execution/lookahead.rb +88 -21
  39. data/lib/graphql/introspection/dynamic_fields.rb +1 -1
  40. data/lib/graphql/introspection/entry_points.rb +11 -5
  41. data/lib/graphql/introspection/schema_type.rb +3 -1
  42. data/lib/graphql/language/block_string.rb +34 -18
  43. data/lib/graphql/language/definition_slice.rb +1 -1
  44. data/lib/graphql/language/document_from_schema_definition.rb +37 -37
  45. data/lib/graphql/language/lexer.rb +271 -177
  46. data/lib/graphql/language/nodes.rb +75 -57
  47. data/lib/graphql/language/parser.rb +707 -1986
  48. data/lib/graphql/language/printer.rb +303 -146
  49. data/lib/graphql/language/sanitized_printer.rb +20 -22
  50. data/lib/graphql/language/static_visitor.rb +167 -0
  51. data/lib/graphql/language/visitor.rb +20 -81
  52. data/lib/graphql/language.rb +1 -0
  53. data/lib/graphql/load_application_object_failed_error.rb +5 -1
  54. data/lib/graphql/pagination/array_connection.rb +3 -3
  55. data/lib/graphql/pagination/connection.rb +28 -1
  56. data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
  57. data/lib/graphql/pagination/relation_connection.rb +3 -3
  58. data/lib/graphql/query/context/scoped_context.rb +101 -0
  59. data/lib/graphql/query/context.rb +36 -98
  60. data/lib/graphql/query/null_context.rb +4 -11
  61. data/lib/graphql/query/validation_pipeline.rb +2 -2
  62. data/lib/graphql/query/variables.rb +3 -3
  63. data/lib/graphql/query.rb +13 -22
  64. data/lib/graphql/railtie.rb +9 -6
  65. data/lib/graphql/rake_task.rb +3 -12
  66. data/lib/graphql/schema/argument.rb +6 -1
  67. data/lib/graphql/schema/base_64_encoder.rb +3 -5
  68. data/lib/graphql/schema/build_from_definition.rb +0 -11
  69. data/lib/graphql/schema/directive/one_of.rb +12 -0
  70. data/lib/graphql/schema/directive/specified_by.rb +14 -0
  71. data/lib/graphql/schema/directive.rb +1 -1
  72. data/lib/graphql/schema/enum.rb +3 -3
  73. data/lib/graphql/schema/field/connection_extension.rb +1 -15
  74. data/lib/graphql/schema/field/scope_extension.rb +8 -1
  75. data/lib/graphql/schema/field.rb +39 -35
  76. data/lib/graphql/schema/has_single_input_argument.rb +156 -0
  77. data/lib/graphql/schema/input_object.rb +2 -2
  78. data/lib/graphql/schema/interface.rb +15 -11
  79. data/lib/graphql/schema/introspection_system.rb +2 -0
  80. data/lib/graphql/schema/loader.rb +0 -2
  81. data/lib/graphql/schema/member/base_dsl_methods.rb +2 -1
  82. data/lib/graphql/schema/member/has_arguments.rb +61 -38
  83. data/lib/graphql/schema/member/has_fields.rb +8 -5
  84. data/lib/graphql/schema/member/has_interfaces.rb +23 -9
  85. data/lib/graphql/schema/member/scoped.rb +19 -0
  86. data/lib/graphql/schema/member/validates_input.rb +3 -3
  87. data/lib/graphql/schema/object.rb +8 -0
  88. data/lib/graphql/schema/printer.rb +8 -7
  89. data/lib/graphql/schema/relay_classic_mutation.rb +6 -128
  90. data/lib/graphql/schema/resolver.rb +16 -8
  91. data/lib/graphql/schema/scalar.rb +3 -3
  92. data/lib/graphql/schema/subscription.rb +11 -4
  93. data/lib/graphql/schema/union.rb +1 -1
  94. data/lib/graphql/schema/unique_within_type.rb +1 -1
  95. data/lib/graphql/schema/warden.rb +96 -94
  96. data/lib/graphql/schema.rb +252 -78
  97. data/lib/graphql/static_validation/all_rules.rb +1 -1
  98. data/lib/graphql/static_validation/base_visitor.rb +1 -1
  99. data/lib/graphql/static_validation/literal_validator.rb +2 -3
  100. data/lib/graphql/static_validation/rules/fields_will_merge.rb +1 -1
  101. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -1
  102. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +2 -2
  103. data/lib/graphql/static_validation/validation_context.rb +5 -5
  104. data/lib/graphql/static_validation/validator.rb +3 -0
  105. data/lib/graphql/static_validation.rb +0 -1
  106. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +3 -2
  107. data/lib/graphql/subscriptions/event.rb +8 -2
  108. data/lib/graphql/subscriptions/serialize.rb +2 -0
  109. data/lib/graphql/subscriptions.rb +14 -12
  110. data/lib/graphql/testing/helpers.rb +129 -0
  111. data/lib/graphql/testing.rb +2 -0
  112. data/lib/graphql/tracing/appoptics_trace.rb +2 -2
  113. data/lib/graphql/tracing/appoptics_tracing.rb +2 -2
  114. data/lib/graphql/tracing/legacy_hooks_trace.rb +74 -0
  115. data/lib/graphql/tracing/platform_tracing.rb +2 -0
  116. data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +3 -1
  117. data/lib/graphql/tracing/sentry_trace.rb +112 -0
  118. data/lib/graphql/tracing/trace.rb +1 -0
  119. data/lib/graphql/tracing.rb +3 -1
  120. data/lib/graphql/types/iso_8601_duration.rb +77 -0
  121. data/lib/graphql/types/relay/connection_behaviors.rb +32 -2
  122. data/lib/graphql/types/relay/edge_behaviors.rb +7 -0
  123. data/lib/graphql/types.rb +1 -0
  124. data/lib/graphql/version.rb +1 -1
  125. data/lib/graphql.rb +6 -5
  126. data/readme.md +12 -2
  127. metadata +46 -38
  128. data/lib/graphql/deprecation.rb +0 -9
  129. data/lib/graphql/filter.rb +0 -59
  130. data/lib/graphql/language/parser.y +0 -560
  131. data/lib/graphql/schema/base_64_bp.rb +0 -26
  132. data/lib/graphql/static_validation/type_stack.rb +0 -216
  133. 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,183 @@ 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
211
+ variable_definition.directives.each do |dir|
212
+ print_string(" ")
213
+ print_directive(dir)
214
+ end
128
215
  end
129
216
 
130
217
  def print_variable_identifier(variable_identifier)
131
- "$#{variable_identifier.name}".dup
218
+ print_string("$")
219
+ print_string(variable_identifier.name)
132
220
  end
133
221
 
134
222
  def print_schema_definition(schema, extension: false)
@@ -140,175 +228,236 @@ module GraphQL
140
228
  return
141
229
  end
142
230
 
143
- out = extension ? "extend schema".dup : "schema".dup
231
+ extension ? print_string("extend schema") : print_string("schema")
232
+
144
233
  if schema.directives.any?
145
234
  schema.directives.each do |dir|
146
- out << "\n "
147
- out << print_node(dir)
235
+ print_string("\n ")
236
+ print_node(dir)
148
237
  end
238
+
149
239
  if !has_conventional_names
150
- out << "\n"
240
+ print_string("\n")
151
241
  end
152
242
  end
153
243
 
154
244
  if !has_conventional_names
155
245
  if schema.directives.empty?
156
- out << " "
246
+ print_string(" ")
157
247
  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 << "}"
248
+ print_string("{\n")
249
+ print_string(" query: #{schema.query}\n") if schema.query
250
+ print_string(" mutation: #{schema.mutation}\n") if schema.mutation
251
+ print_string(" subscription: #{schema.subscription}\n") if schema.subscription
252
+ print_string("}")
163
253
  end
164
- out
165
254
  end
166
255
 
256
+
167
257
  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)
258
+ extension ? print_string("extend ") : print_description(scalar_type)
259
+ print_string("scalar ")
260
+ print_string(scalar_type.name)
261
+ print_directives(scalar_type.directives)
171
262
  end
172
263
 
173
264
  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)
265
+ extension ? print_string("extend ") : print_description(object_type)
266
+ print_string("type ")
267
+ print_string(object_type.name)
268
+ print_implements(object_type) unless object_type.interfaces.empty?
269
+ print_directives(object_type.directives)
270
+ print_field_definitions(object_type.fields)
179
271
  end
180
272
 
181
273
  def print_implements(type)
182
- " implements #{type.interfaces.map(&:name).join(" & ")}"
274
+ print_string(" implements ")
275
+ i = 0
276
+ type.interfaces.each do |int|
277
+ if i > 0
278
+ print_string(" & ")
279
+ end
280
+ print_string(int.name)
281
+ i += 1
282
+ end
183
283
  end
184
284
 
185
285
  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)
286
+ print_string(input_value.name)
287
+ print_string(": ")
288
+ print_node(input_value.type)
289
+ unless input_value.default_value.nil?
290
+ print_string(" = ")
291
+ print_node(input_value.default_value)
292
+ end
293
+ print_directives(input_value.directives)
189
294
  end
190
295
 
191
296
  def print_arguments(arguments, indent: "")
192
- if arguments.all?{ |arg| !arg.description }
193
- return "(#{arguments.map{ |arg| print_input_value_definition(arg) }.join(", ")})"
297
+ if arguments.all? { |arg| !arg.description }
298
+ print_string("(")
299
+ arguments.each_with_index do |arg, i|
300
+ print_input_value_definition(arg)
301
+ print_string(", ") if i < arguments.size - 1
302
+ end
303
+ print_string(")")
304
+ return
194
305
  end
195
306
 
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})"
307
+ print_string("(\n")
308
+ arguments.each_with_index do |arg, i|
309
+ print_description(arg, indent: " " + indent, first_in_block: i == 0)
310
+ print_string(" ")
311
+ print_string(indent)
312
+ print_input_value_definition(arg)
313
+ print_string("\n") if i < arguments.size - 1
314
+ end
315
+ print_string("\n")
316
+ print_string(indent)
317
+ print_string(")")
202
318
  end
203
319
 
204
320
  def print_field_definition(field)
205
- out = field.name.dup
321
+ print_string(field.name)
206
322
  unless field.arguments.empty?
207
- out << print_arguments(field.arguments, indent: " ")
323
+ print_arguments(field.arguments, indent: " ")
208
324
  end
209
- out << ": #{print_node(field.type)}"
210
- out << print_directives(field.directives)
325
+ print_string(": ")
326
+ print_node(field.type)
327
+ print_directives(field.directives)
211
328
  end
212
329
 
213
330
  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)
331
+ extension ? print_string("extend ") : print_description(interface_type)
332
+ print_string("interface ")
333
+ print_string(interface_type.name)
334
+ print_implements(interface_type) if interface_type.interfaces.any?
335
+ print_directives(interface_type.directives)
336
+ print_field_definitions(interface_type.fields)
219
337
  end
220
338
 
221
339
  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(" | ")
340
+ extension ? print_string("extend ") : print_description(union_type)
341
+ print_string("union ")
342
+ print_string(union_type.name)
343
+ print_directives(union_type.directives)
344
+ if union_type.types.any?
345
+ print_string(" = ")
346
+ i = 0
347
+ union_type.types.each do |t|
348
+ if i > 0
349
+ print_string(" | ")
350
+ end
351
+ print_string(t.name)
352
+ i += 1
353
+ end
354
+ end
226
355
  end
227
356
 
228
357
  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)
358
+ extension ? print_string("extend ") : print_description(enum_type)
359
+ print_string("enum ")
360
+ print_string(enum_type.name)
361
+ print_directives(enum_type.directives)
362
+ if enum_type.values.any?
363
+ print_string(" {\n")
364
+ enum_type.values.each.with_index do |value, i|
365
+ print_description(value, indent: " ", first_in_block: i == 0)
366
+ print_enum_value_definition(value)
367
+ end
368
+ print_string("}")
234
369
  end
235
- out << "}"
236
370
  end
237
371
 
238
372
  def print_enum_value_definition(enum_value)
239
- out = " #{enum_value.name}".dup
240
- out << print_directives(enum_value.directives)
241
- out << "\n"
373
+ print_string(" ")
374
+ print_string(enum_value.name)
375
+ print_directives(enum_value.directives)
376
+ print_string("\n")
242
377
  end
243
378
 
244
379
  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)
380
+ extension ? print_string("extend ") : print_description(input_object_type)
381
+ print_string("input ")
382
+ print_string(input_object_type.name)
383
+ print_directives(input_object_type.directives)
248
384
  if !input_object_type.fields.empty?
249
- out << " {\n"
385
+ print_string(" {\n")
250
386
  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"
387
+ print_description(field, indent: " ", first_in_block: i == 0)
388
+ print_string(" ")
389
+ print_input_value_definition(field)
390
+ print_string("\n")
253
391
  end
254
- out << "}"
392
+ print_string("}")
255
393
  end
256
- out
257
394
  end
258
395
 
259
396
  def print_directive_definition(directive)
260
- out = print_description(directive)
261
- out << "directive @#{directive.name}"
397
+ print_description(directive)
398
+ print_string("directive @")
399
+ print_string(directive.name)
262
400
 
263
401
  if directive.arguments.any?
264
- out << print_arguments(directive.arguments)
402
+ print_arguments(directive.arguments)
265
403
  end
266
404
 
267
405
  if directive.repeatable
268
- out << " repeatable"
406
+ print_string(" repeatable")
269
407
  end
270
408
 
271
- out << " on #{directive.locations.map(&:name).join(' | ')}"
409
+ print_string(" on ")
410
+ i = 0
411
+ directive.locations.each do |loc|
412
+ if i > 0
413
+ print_string(" | ")
414
+ end
415
+ print_string(loc.name)
416
+ i += 1
417
+ end
272
418
  end
273
419
 
274
420
  def print_description(node, indent: "", first_in_block: true)
275
- return ''.dup unless node.description
421
+ return unless node.description
276
422
 
277
- description = indent != '' && !first_in_block ? "\n".dup : "".dup
278
- description << GraphQL::Language::BlockString.print(node.description, indent: indent)
423
+ print_string("\n") if indent != "" && !first_in_block
424
+ print_string(GraphQL::Language::BlockString.print(node.description, indent: indent))
279
425
  end
280
426
 
281
427
  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 << "}"
428
+ return if fields.empty?
429
+
430
+ print_string(" {\n")
431
+ i = 0
432
+ fields.each do |field|
433
+ print_description(field, indent: " ", first_in_block: i == 0)
434
+ print_string(" ")
435
+ print_field_definition(field)
436
+ print_string("\n")
437
+ i += 1
291
438
  end
439
+ print_string("}")
292
440
  end
293
441
 
294
442
  def print_directives(directives)
295
- if directives.any?
296
- directives.map { |d| " #{print_directive(d)}" }.join
297
- else
298
- ""
443
+ return if directives.empty?
444
+
445
+ directives.each do |d|
446
+ print_string(" ")
447
+ print_directive(d)
299
448
  end
300
449
  end
301
450
 
302
451
  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
- ""
452
+ return if selections.empty?
453
+
454
+ print_string(" {\n")
455
+ selections.each do |selection|
456
+ print_node(selection, indent: indent + " ")
457
+ print_string("\n")
311
458
  end
459
+ print_string(indent)
460
+ print_string("}")
312
461
  end
313
462
 
314
463
  def print_node(node, indent: "")
@@ -382,19 +531,27 @@ module GraphQL
382
531
  when Nodes::DirectiveDefinition
383
532
  print_directive_definition(node)
384
533
  when FalseClass, Float, Integer, NilClass, String, TrueClass, Symbol
385
- GraphQL::Language.serialize(node)
534
+ print_string(GraphQL::Language.serialize(node))
386
535
  when Array
387
- "[#{node.map { |v| print_node(v) }.join(", ")}]".dup
536
+ print_string("[")
537
+ node.each_with_index do |v, i|
538
+ print_node(v)
539
+ print_string(", ") if i < node.length - 1
540
+ end
541
+ print_string("]")
388
542
  when Hash
389
- "{#{node.map { |k, v| "#{k}: #{print_node(v)}" }.join(", ")}}".dup
543
+ print_string("{")
544
+ node.each_with_index do |(k, v), i|
545
+ print_string(k)
546
+ print_string(": ")
547
+ print_node(v)
548
+ print_string(", ") if i < node.length - 1
549
+ end
550
+ print_string("}")
390
551
  else
391
- GraphQL::Language.serialize(node.to_s)
552
+ print_string(GraphQL::Language.serialize(node.to_s))
392
553
  end
393
554
  end
394
-
395
- private
396
-
397
- attr_reader :node
398
555
  end
399
556
  end
400
557
  end