graphql 2.0.28 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,158 @@ 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_node(argument.value)
79
+ end
80
+
81
+ def print_input_object(input_object)
82
+ print_string("{")
83
+ input_object.arguments.each_with_index do |a, i|
84
+ print_argument(a)
85
+ print_string(", ") if i < input_object.arguments.size - 1
86
+ end
87
+ print_string("}")
39
88
  end
40
89
 
41
90
  def print_directive(directive)
42
- out = "@#{directive.name}".dup
91
+ print_string("@#{directive.name}")
43
92
 
44
93
  if directive.arguments.any?
45
- out << "(#{directive.arguments.map { |a| print_argument(a) }.join(", ")})"
94
+ print_string("(")
95
+ directive.arguments.each_with_index do |a, i|
96
+ print_argument(a)
97
+ print_string(", ") if i < directive.arguments.size - 1
98
+ end
99
+ print_string(")")
46
100
  end
47
-
48
- out
49
101
  end
50
102
 
51
103
  def print_enum(enum)
52
- "#{enum.name}".dup
104
+ print_string(enum.name)
53
105
  end
54
106
 
55
107
  def print_null_value
56
- "null".dup
108
+ print_string("null")
57
109
  end
58
110
 
59
111
  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
112
+ print_string(indent)
113
+ print_string("#{field.alias}: ") if field.alias
114
+ print_string(field.name)
115
+ if field.arguments.any?
116
+ print_string("(")
117
+ field.arguments.each_with_index do |a, i|
118
+ print_argument(a)
119
+ print_string(", ") if i < field.arguments.size - 1
120
+ end
121
+ print_string(")")
122
+ end
123
+ print_directives(field.directives)
124
+ print_selections(field.selections, indent: indent)
67
125
  end
68
126
 
69
127
  def print_fragment_definition(fragment_def, indent: "")
70
- out = "#{indent}fragment #{fragment_def.name}".dup
128
+ print_string("#{indent}fragment #{fragment_def.name}")
71
129
  if fragment_def.type
72
- out << " on #{print_node(fragment_def.type)}"
130
+ print_string(" on ")
131
+ print_node(fragment_def.type)
73
132
  end
74
- out << print_directives(fragment_def.directives)
75
- out << print_selections(fragment_def.selections, indent: indent)
76
- out
133
+ print_directives(fragment_def.directives)
134
+ print_selections(fragment_def.selections, indent: indent)
77
135
  end
78
136
 
79
137
  def print_fragment_spread(fragment_spread, indent: "")
80
- out = "#{indent}...#{fragment_spread.name}".dup
81
- out << print_directives(fragment_spread.directives)
82
- out
138
+ print_string("#{indent}...#{fragment_spread.name}")
139
+ print_directives(fragment_spread.directives)
83
140
  end
84
141
 
85
142
  def print_inline_fragment(inline_fragment, indent: "")
86
- out = "#{indent}...".dup
143
+ print_string("#{indent}...")
87
144
  if inline_fragment.type
88
- out << " on #{print_node(inline_fragment.type)}"
145
+ print_string(" on ")
146
+ print_node(inline_fragment.type)
89
147
  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(", ")}}"
148
+ print_directives(inline_fragment.directives)
149
+ print_selections(inline_fragment.selections, indent: indent)
97
150
  end
98
151
 
99
152
  def print_list_type(list_type)
100
- "[#{print_node(list_type.of_type)}]".dup
153
+ print_string("[")
154
+ print_node(list_type.of_type)
155
+ print_string("]")
101
156
  end
102
157
 
103
158
  def print_non_null_type(non_null_type)
104
- "#{print_node(non_null_type.of_type)}!".dup
159
+ print_node(non_null_type.of_type)
160
+ print_string("!")
105
161
  end
106
162
 
107
163
  def print_operation_definition(operation_definition, indent: "")
108
- out = "#{indent}#{operation_definition.operation_type}".dup
109
- out << " #{operation_definition.name}" if operation_definition.name
164
+ print_string("#{indent}#{operation_definition.operation_type}")
165
+ print_string(" #{operation_definition.name}") if operation_definition.name
110
166
 
111
167
  if operation_definition.variables.any?
112
- out << "(#{operation_definition.variables.map { |v| print_variable_definition(v) }.join(", ")})"
168
+ print_string("(")
169
+ operation_definition.variables.each_with_index do |v, i|
170
+ print_variable_definition(v)
171
+ print_string(", ") if i < operation_definition.variables.size - 1
172
+ end
173
+ print_string(")")
113
174
  end
114
175
 
115
- out << print_directives(operation_definition.directives)
116
- out << print_selections(operation_definition.selections, indent: indent)
117
- out
176
+ print_directives(operation_definition.directives)
177
+ print_selections(operation_definition.selections, indent: indent)
118
178
  end
119
179
 
120
180
  def print_type_name(type_name)
121
- "#{type_name.name}".dup
181
+ print_string(type_name.name)
122
182
  end
123
183
 
124
184
  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
185
+ print_string("$#{variable_definition.name}: ")
186
+ print_node(variable_definition.type)
187
+ unless variable_definition.default_value.nil?
188
+ print_string(" = ")
189
+ print_node(variable_definition.default_value)
190
+ end
128
191
  end
129
192
 
130
193
  def print_variable_identifier(variable_identifier)
131
- "$#{variable_identifier.name}".dup
194
+ print_string("$#{variable_identifier.name}")
132
195
  end
133
196
 
134
197
  def print_schema_definition(schema, extension: false)
@@ -140,175 +203,193 @@ module GraphQL
140
203
  return
141
204
  end
142
205
 
143
- out = extension ? "extend schema".dup : "schema".dup
206
+ extension ? print_string("extend schema") : print_string("schema")
207
+
144
208
  if schema.directives.any?
145
209
  schema.directives.each do |dir|
146
- out << "\n "
147
- out << print_node(dir)
210
+ print_string("\n ")
211
+ print_node(dir)
148
212
  end
213
+
149
214
  if !has_conventional_names
150
- out << "\n"
215
+ print_string("\n")
151
216
  end
152
217
  end
153
218
 
154
219
  if !has_conventional_names
155
220
  if schema.directives.empty?
156
- out << " "
221
+ print_string(" ")
157
222
  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 << "}"
223
+ print_string("{\n")
224
+ print_string(" query: #{schema.query}\n") if schema.query
225
+ print_string(" mutation: #{schema.mutation}\n") if schema.mutation
226
+ print_string(" subscription: #{schema.subscription}\n") if schema.subscription
227
+ print_string("}")
163
228
  end
164
- out
165
229
  end
166
230
 
231
+
167
232
  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)
233
+ extension ? print_string("extend ") : print_description(scalar_type)
234
+ print_string("scalar #{scalar_type.name}")
235
+ print_directives(scalar_type.directives)
171
236
  end
172
237
 
173
238
  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)
239
+ extension ? print_string("extend ") : print_description(object_type)
240
+ print_string("type #{object_type.name}")
241
+ print_implements(object_type) unless object_type.interfaces.empty?
242
+ print_directives(object_type.directives)
243
+ print_field_definitions(object_type.fields)
179
244
  end
180
245
 
181
246
  def print_implements(type)
182
- " implements #{type.interfaces.map(&:name).join(" & ")}"
247
+ print_string(" implements #{type.interfaces.map(&:name).join(" & ")}")
183
248
  end
184
249
 
185
250
  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)
251
+ print_string("#{input_value.name}: ")
252
+ print_node(input_value.type)
253
+ unless input_value.default_value.nil?
254
+ print_string(" = ")
255
+ print_node(input_value.default_value)
256
+ end
257
+ print_directives(input_value.directives)
189
258
  end
190
259
 
191
260
  def print_arguments(arguments, indent: "")
192
- if arguments.all?{ |arg| !arg.description }
193
- return "(#{arguments.map{ |arg| print_input_value_definition(arg) }.join(", ")})"
261
+ if arguments.all? { |arg| !arg.description }
262
+ print_string("(")
263
+ arguments.each_with_index do |arg, i|
264
+ print_input_value_definition(arg)
265
+ print_string(", ") if i < arguments.size - 1
266
+ end
267
+ print_string(")")
268
+ return
194
269
  end
195
270
 
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})"
271
+ print_string("(\n")
272
+ arguments.each_with_index do |arg, i|
273
+ print_description(arg, indent: " " + indent, first_in_block: i == 0)
274
+ print_string(" #{indent}")
275
+ print_input_value_definition(arg)
276
+ print_string("\n") if i < arguments.size - 1
277
+ end
278
+ print_string("\n#{indent})")
202
279
  end
203
280
 
204
281
  def print_field_definition(field)
205
- out = field.name.dup
282
+ print_string(field.name)
206
283
  unless field.arguments.empty?
207
- out << print_arguments(field.arguments, indent: " ")
284
+ print_arguments(field.arguments, indent: " ")
208
285
  end
209
- out << ": #{print_node(field.type)}"
210
- out << print_directives(field.directives)
286
+ print_string(": ")
287
+ print_node(field.type)
288
+ print_directives(field.directives)
211
289
  end
212
290
 
213
291
  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)
292
+ extension ? print_string("extend ") : print_description(interface_type)
293
+ print_string("interface #{interface_type.name}")
294
+ print_implements(interface_type) if interface_type.interfaces.any?
295
+ print_directives(interface_type.directives)
296
+ print_field_definitions(interface_type.fields)
219
297
  end
220
298
 
221
299
  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(" | ")
300
+ extension ? print_string("extend ") : print_description(union_type)
301
+ print_string("union #{union_type.name}")
302
+ print_directives(union_type.directives)
303
+ print_string(" = #{union_type.types.map(&:name).join(" | ")}")
226
304
  end
227
305
 
228
306
  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"
307
+ extension ? print_string("extend ") : print_description(enum_type)
308
+ print_string("enum #{enum_type.name}")
309
+ print_directives(enum_type.directives)
310
+ print_string(" {\n")
231
311
  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)
312
+ print_description(value, indent: " ", first_in_block: i == 0)
313
+ print_enum_value_definition(value)
234
314
  end
235
- out << "}"
315
+ print_string("}")
236
316
  end
237
317
 
238
318
  def print_enum_value_definition(enum_value)
239
- out = " #{enum_value.name}".dup
240
- out << print_directives(enum_value.directives)
241
- out << "\n"
319
+ print_string(" #{enum_value.name}")
320
+ print_directives(enum_value.directives)
321
+ print_string("\n")
242
322
  end
243
323
 
244
324
  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)
325
+ extension ? print_string("extend ") : print_description(input_object_type)
326
+ print_string("input #{input_object_type.name}")
327
+ print_directives(input_object_type.directives)
248
328
  if !input_object_type.fields.empty?
249
- out << " {\n"
329
+ print_string(" {\n")
250
330
  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"
331
+ print_description(field, indent: " ", first_in_block: i == 0)
332
+ print_string(" ")
333
+ print_input_value_definition(field)
334
+ print_string("\n")
253
335
  end
254
- out << "}"
336
+ print_string("}")
255
337
  end
256
- out
257
338
  end
258
339
 
259
340
  def print_directive_definition(directive)
260
- out = print_description(directive)
261
- out << "directive @#{directive.name}"
341
+ print_description(directive)
342
+ print_string("directive @#{directive.name}")
262
343
 
263
344
  if directive.arguments.any?
264
- out << print_arguments(directive.arguments)
345
+ print_arguments(directive.arguments)
265
346
  end
266
347
 
267
348
  if directive.repeatable
268
- out << " repeatable"
349
+ print_string(" repeatable")
269
350
  end
270
351
 
271
- out << " on #{directive.locations.map(&:name).join(' | ')}"
352
+ print_string(" on #{directive.locations.map(&:name).join(" | ")}")
272
353
  end
273
354
 
274
355
  def print_description(node, indent: "", first_in_block: true)
275
- return ''.dup unless node.description
356
+ return unless node.description
276
357
 
277
- description = indent != '' && !first_in_block ? "\n".dup : "".dup
278
- description << GraphQL::Language::BlockString.print(node.description, indent: indent)
358
+ print_string("\n") if indent != "" && !first_in_block
359
+ print_string(GraphQL::Language::BlockString.print(node.description, indent: indent))
279
360
  end
280
361
 
281
362
  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 << "}"
363
+ return if fields.empty?
364
+
365
+ print_string(" {\n")
366
+ fields.each.with_index do |field, i|
367
+ print_description(field, indent: " ", first_in_block: i == 0)
368
+ print_string(" ")
369
+ print_field_definition(field)
370
+ print_string("\n")
291
371
  end
372
+ print_string("}")
292
373
  end
293
374
 
294
375
  def print_directives(directives)
295
- if directives.any?
296
- directives.map { |d| " #{print_directive(d)}" }.join
297
- else
298
- ""
376
+ return if directives.empty?
377
+
378
+ directives.each do |d|
379
+ print_string(" ")
380
+ print_directive(d)
299
381
  end
300
382
  end
301
383
 
302
384
  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
- ""
385
+ return if selections.empty?
386
+
387
+ print_string(" {\n")
388
+ selections.each do |selection|
389
+ print_node(selection, indent: indent + " ")
390
+ print_string("\n")
311
391
  end
392
+ print_string("#{indent}}")
312
393
  end
313
394
 
314
395
  def print_node(node, indent: "")
@@ -382,19 +463,26 @@ module GraphQL
382
463
  when Nodes::DirectiveDefinition
383
464
  print_directive_definition(node)
384
465
  when FalseClass, Float, Integer, NilClass, String, TrueClass, Symbol
385
- GraphQL::Language.serialize(node)
466
+ print_string(GraphQL::Language.serialize(node))
386
467
  when Array
387
- "[#{node.map { |v| print_node(v) }.join(", ")}]".dup
468
+ print_string("[")
469
+ node.each_with_index do |v, i|
470
+ print_node(v)
471
+ print_string(", ") if i < node.length - 1
472
+ end
473
+ print_string("]")
388
474
  when Hash
389
- "{#{node.map { |k, v| "#{k}: #{print_node(v)}" }.join(", ")}}".dup
475
+ print_string("{")
476
+ node.each_with_index do |(k, v), i|
477
+ print_string("#{k}: ")
478
+ print_node(v)
479
+ print_string(", ") if i < node.length - 1
480
+ end
481
+ print_string("}")
390
482
  else
391
- GraphQL::Language.serialize(node.to_s)
483
+ print_string(GraphQL::Language.serialize(node.to_s))
392
484
  end
393
485
  end
394
-
395
- private
396
-
397
- attr_reader :node
398
486
  end
399
487
  end
400
488
  end
@@ -40,7 +40,7 @@ module GraphQL
40
40
  case node
41
41
  when FalseClass, Float, Integer, String, TrueClass
42
42
  if @current_argument && redact_argument_value?(@current_argument, node)
43
- redacted_argument_value(@current_argument)
43
+ print_string(redacted_argument_value(@current_argument))
44
44
  else
45
45
  super
46
46
  end
@@ -51,9 +51,8 @@ module GraphQL
51
51
  @current_input_type = @current_input_type.of_type if @current_input_type.non_null?
52
52
  end
53
53
 
54
- res = super
54
+ super
55
55
  @current_input_type = old_input_type
56
- res
57
56
  else
58
57
  super
59
58
  end
@@ -89,11 +88,12 @@ module GraphQL
89
88
  else
90
89
  argument.value
91
90
  end
92
- res = "#{argument.name}: #{print_node(argument_value)}".dup
91
+
92
+ print_string("#{argument.name}: ")
93
+ print_node(argument_value)
93
94
 
94
95
  @current_input_type = old_input_type
95
96
  @current_argument = old_current_argument
96
- res
97
97
  end
98
98
 
99
99
  def coerce_argument_value_to_list?(type, value)
@@ -116,9 +116,8 @@ module GraphQL
116
116
  @current_field = query.get_field(@current_type, field.name)
117
117
  old_type = @current_type
118
118
  @current_type = @current_field.type.unwrap
119
- res = super
119
+ super
120
120
  @current_type = old_type
121
- res
122
121
  end
123
122
 
124
123
  def print_inline_fragment(inline_fragment, indent: "")
@@ -128,31 +127,26 @@ module GraphQL
128
127
  @current_type = query.get_type(inline_fragment.type.name)
129
128
  end
130
129
 
131
- res = super
130
+ super
132
131
 
133
132
  @current_type = old_type
134
-
135
- res
136
133
  end
137
134
 
138
135
  def print_fragment_definition(fragment_def, indent: "")
139
136
  old_type = @current_type
140
137
  @current_type = query.get_type(fragment_def.type.name)
141
138
 
142
- res = super
139
+ super
143
140
 
144
141
  @current_type = old_type
145
-
146
- res
147
142
  end
148
143
 
149
144
  def print_directive(directive)
150
145
  @current_directive = query.schema.directives[directive.name]
151
146
 
152
- res = super
147
+ super
153
148
 
154
149
  @current_directive = nil
155
- res
156
150
  end
157
151
 
158
152
  # Print the operation definition but do not include the variable
@@ -162,16 +156,15 @@ module GraphQL
162
156
  @current_type = query.schema.public_send(operation_definition.operation_type)
163
157
 
164
158
  if @inline_variables
165
- out = "#{indent}#{operation_definition.operation_type}".dup
166
- out << " #{operation_definition.name}" if operation_definition.name
167
- out << print_directives(operation_definition.directives)
168
- out << print_selections(operation_definition.selections, indent: indent)
159
+ print_string("#{indent}#{operation_definition.operation_type}")
160
+ print_string(" #{operation_definition.name}") if operation_definition.name
161
+ print_directives(operation_definition.directives)
162
+ print_selections(operation_definition.selections, indent: indent)
169
163
  else
170
- out = super
164
+ super
171
165
  end
172
166
 
173
167
  @current_type = old_type
174
- out
175
168
  end
176
169
 
177
170
  private