graphql 2.0.13 → 2.3.10

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.

Potentially problematic release.


This version of graphql might be problematic. Click here for more details.

Files changed (228) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install/mutation_root_generator.rb +2 -2
  3. data/lib/generators/graphql/install/templates/base_mutation.erb +2 -0
  4. data/lib/generators/graphql/install/templates/mutation_type.erb +2 -0
  5. data/lib/generators/graphql/install_generator.rb +3 -0
  6. data/lib/generators/graphql/mutation_delete_generator.rb +1 -1
  7. data/lib/generators/graphql/mutation_update_generator.rb +1 -1
  8. data/lib/generators/graphql/relay.rb +18 -1
  9. data/lib/generators/graphql/templates/base_argument.erb +2 -0
  10. data/lib/generators/graphql/templates/base_connection.erb +2 -0
  11. data/lib/generators/graphql/templates/base_edge.erb +2 -0
  12. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  13. data/lib/generators/graphql/templates/base_field.erb +2 -0
  14. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  15. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  16. data/lib/generators/graphql/templates/base_object.erb +2 -0
  17. data/lib/generators/graphql/templates/base_resolver.erb +6 -0
  18. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  19. data/lib/generators/graphql/templates/base_union.erb +2 -0
  20. data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
  21. data/lib/generators/graphql/templates/loader.erb +2 -0
  22. data/lib/generators/graphql/templates/mutation.erb +2 -0
  23. data/lib/generators/graphql/templates/node_type.erb +2 -0
  24. data/lib/generators/graphql/templates/query_type.erb +2 -0
  25. data/lib/generators/graphql/templates/schema.erb +8 -0
  26. data/lib/graphql/analysis/analyzer.rb +89 -0
  27. data/lib/graphql/analysis/field_usage.rb +82 -0
  28. data/lib/graphql/analysis/max_query_complexity.rb +20 -0
  29. data/lib/graphql/analysis/max_query_depth.rb +20 -0
  30. data/lib/graphql/analysis/query_complexity.rb +183 -0
  31. data/lib/graphql/analysis/query_depth.rb +58 -0
  32. data/lib/graphql/analysis/visitor.rb +283 -0
  33. data/lib/graphql/analysis.rb +92 -1
  34. data/lib/graphql/backtrace/inspect_result.rb +0 -12
  35. data/lib/graphql/backtrace/table.rb +2 -2
  36. data/lib/graphql/backtrace/trace.rb +93 -0
  37. data/lib/graphql/backtrace/tracer.rb +1 -1
  38. data/lib/graphql/backtrace.rb +2 -1
  39. data/lib/graphql/coercion_error.rb +1 -9
  40. data/lib/graphql/dataloader/async_dataloader.rb +88 -0
  41. data/lib/graphql/dataloader/null_dataloader.rb +1 -1
  42. data/lib/graphql/dataloader/request.rb +5 -0
  43. data/lib/graphql/dataloader/source.rb +89 -45
  44. data/lib/graphql/dataloader.rb +115 -142
  45. data/lib/graphql/duration_encoding_error.rb +16 -0
  46. data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
  47. data/lib/graphql/execution/interpreter/arguments.rb +1 -1
  48. data/lib/graphql/execution/interpreter/arguments_cache.rb +33 -33
  49. data/lib/graphql/execution/interpreter/resolve.rb +19 -0
  50. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +175 -0
  51. data/lib/graphql/execution/interpreter/runtime.rb +331 -455
  52. data/lib/graphql/execution/interpreter.rb +125 -61
  53. data/lib/graphql/execution/lazy.rb +6 -12
  54. data/lib/graphql/execution/lookahead.rb +124 -46
  55. data/lib/graphql/execution/multiplex.rb +3 -117
  56. data/lib/graphql/execution.rb +0 -1
  57. data/lib/graphql/introspection/directive_type.rb +3 -3
  58. data/lib/graphql/introspection/dynamic_fields.rb +1 -1
  59. data/lib/graphql/introspection/entry_points.rb +11 -5
  60. data/lib/graphql/introspection/field_type.rb +2 -2
  61. data/lib/graphql/introspection/schema_type.rb +10 -13
  62. data/lib/graphql/introspection/type_type.rb +17 -10
  63. data/lib/graphql/introspection.rb +3 -2
  64. data/lib/graphql/language/block_string.rb +34 -18
  65. data/lib/graphql/language/definition_slice.rb +1 -1
  66. data/lib/graphql/language/document_from_schema_definition.rb +75 -59
  67. data/lib/graphql/language/lexer.rb +358 -1506
  68. data/lib/graphql/language/nodes.rb +166 -93
  69. data/lib/graphql/language/parser.rb +795 -1953
  70. data/lib/graphql/language/printer.rb +340 -160
  71. data/lib/graphql/language/sanitized_printer.rb +21 -23
  72. data/lib/graphql/language/static_visitor.rb +167 -0
  73. data/lib/graphql/language/visitor.rb +188 -141
  74. data/lib/graphql/language.rb +61 -1
  75. data/lib/graphql/load_application_object_failed_error.rb +5 -1
  76. data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
  77. data/lib/graphql/pagination/array_connection.rb +6 -6
  78. data/lib/graphql/pagination/connection.rb +33 -6
  79. data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
  80. data/lib/graphql/query/context/scoped_context.rb +101 -0
  81. data/lib/graphql/query/context.rb +117 -112
  82. data/lib/graphql/query/null_context.rb +12 -25
  83. data/lib/graphql/query/validation_pipeline.rb +6 -5
  84. data/lib/graphql/query/variables.rb +3 -3
  85. data/lib/graphql/query.rb +86 -30
  86. data/lib/graphql/railtie.rb +9 -6
  87. data/lib/graphql/rake_task.rb +29 -11
  88. data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
  89. data/lib/graphql/schema/addition.rb +59 -23
  90. data/lib/graphql/schema/always_visible.rb +11 -0
  91. data/lib/graphql/schema/argument.rb +55 -26
  92. data/lib/graphql/schema/base_64_encoder.rb +3 -5
  93. data/lib/graphql/schema/build_from_definition.rb +56 -32
  94. data/lib/graphql/schema/directive/one_of.rb +24 -0
  95. data/lib/graphql/schema/directive/specified_by.rb +14 -0
  96. data/lib/graphql/schema/directive/transform.rb +1 -1
  97. data/lib/graphql/schema/directive.rb +15 -3
  98. data/lib/graphql/schema/enum.rb +35 -24
  99. data/lib/graphql/schema/enum_value.rb +2 -3
  100. data/lib/graphql/schema/field/connection_extension.rb +2 -16
  101. data/lib/graphql/schema/field/scope_extension.rb +8 -1
  102. data/lib/graphql/schema/field.rb +147 -107
  103. data/lib/graphql/schema/field_extension.rb +1 -4
  104. data/lib/graphql/schema/find_inherited_value.rb +2 -7
  105. data/lib/graphql/schema/has_single_input_argument.rb +158 -0
  106. data/lib/graphql/schema/input_object.rb +47 -11
  107. data/lib/graphql/schema/interface.rb +15 -21
  108. data/lib/graphql/schema/introspection_system.rb +7 -17
  109. data/lib/graphql/schema/late_bound_type.rb +10 -0
  110. data/lib/graphql/schema/list.rb +2 -2
  111. data/lib/graphql/schema/loader.rb +2 -3
  112. data/lib/graphql/schema/member/base_dsl_methods.rb +18 -14
  113. data/lib/graphql/schema/member/build_type.rb +11 -3
  114. data/lib/graphql/schema/member/has_arguments.rb +170 -130
  115. data/lib/graphql/schema/member/has_ast_node.rb +12 -0
  116. data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
  117. data/lib/graphql/schema/member/has_directives.rb +81 -61
  118. data/lib/graphql/schema/member/has_fields.rb +100 -38
  119. data/lib/graphql/schema/member/has_interfaces.rb +65 -10
  120. data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
  121. data/lib/graphql/schema/member/has_validators.rb +32 -6
  122. data/lib/graphql/schema/member/relay_shortcuts.rb +19 -0
  123. data/lib/graphql/schema/member/scoped.rb +19 -0
  124. data/lib/graphql/schema/member/type_system_helpers.rb +16 -0
  125. data/lib/graphql/schema/member/validates_input.rb +3 -3
  126. data/lib/graphql/schema/mutation.rb +7 -0
  127. data/lib/graphql/schema/object.rb +16 -5
  128. data/lib/graphql/schema/printer.rb +11 -8
  129. data/lib/graphql/schema/relay_classic_mutation.rb +7 -129
  130. data/lib/graphql/schema/resolver/has_payload_type.rb +9 -9
  131. data/lib/graphql/schema/resolver.rb +47 -32
  132. data/lib/graphql/schema/scalar.rb +3 -3
  133. data/lib/graphql/schema/subscription.rb +11 -4
  134. data/lib/graphql/schema/subset.rb +397 -0
  135. data/lib/graphql/schema/timeout.rb +25 -29
  136. data/lib/graphql/schema/type_expression.rb +2 -2
  137. data/lib/graphql/schema/type_membership.rb +3 -0
  138. data/lib/graphql/schema/union.rb +11 -2
  139. data/lib/graphql/schema/unique_within_type.rb +1 -1
  140. data/lib/graphql/schema/validator/all_validator.rb +60 -0
  141. data/lib/graphql/schema/validator.rb +4 -2
  142. data/lib/graphql/schema/warden.rb +238 -93
  143. data/lib/graphql/schema.rb +498 -103
  144. data/lib/graphql/static_validation/all_rules.rb +2 -1
  145. data/lib/graphql/static_validation/base_visitor.rb +7 -6
  146. data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
  147. data/lib/graphql/static_validation/literal_validator.rb +24 -7
  148. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
  149. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
  150. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -2
  151. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
  152. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
  153. data/lib/graphql/static_validation/rules/fields_will_merge.rb +10 -10
  154. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  155. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
  156. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
  157. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
  158. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  159. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  160. data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
  161. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -4
  162. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
  163. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
  164. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
  165. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +1 -1
  166. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  167. data/lib/graphql/static_validation/validation_context.rb +5 -5
  168. data/lib/graphql/static_validation/validator.rb +4 -1
  169. data/lib/graphql/static_validation.rb +0 -1
  170. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +11 -4
  171. data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
  172. data/lib/graphql/subscriptions/event.rb +11 -10
  173. data/lib/graphql/subscriptions/serialize.rb +2 -0
  174. data/lib/graphql/subscriptions.rb +20 -13
  175. data/lib/graphql/testing/helpers.rb +151 -0
  176. data/lib/graphql/testing.rb +2 -0
  177. data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
  178. data/lib/graphql/tracing/appoptics_trace.rb +251 -0
  179. data/lib/graphql/tracing/appoptics_tracing.rb +2 -2
  180. data/lib/graphql/tracing/appsignal_trace.rb +77 -0
  181. data/lib/graphql/tracing/data_dog_trace.rb +183 -0
  182. data/lib/graphql/tracing/data_dog_tracing.rb +9 -21
  183. data/lib/graphql/{execution/instrumentation.rb → tracing/legacy_hooks_trace.rb} +10 -28
  184. data/lib/graphql/tracing/legacy_trace.rb +69 -0
  185. data/lib/graphql/tracing/new_relic_trace.rb +75 -0
  186. data/lib/graphql/tracing/notifications_trace.rb +45 -0
  187. data/lib/graphql/tracing/platform_trace.rb +118 -0
  188. data/lib/graphql/tracing/platform_tracing.rb +17 -3
  189. data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +4 -2
  190. data/lib/graphql/tracing/prometheus_trace.rb +89 -0
  191. data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
  192. data/lib/graphql/tracing/scout_trace.rb +72 -0
  193. data/lib/graphql/tracing/sentry_trace.rb +112 -0
  194. data/lib/graphql/tracing/statsd_trace.rb +56 -0
  195. data/lib/graphql/tracing/trace.rb +76 -0
  196. data/lib/graphql/tracing.rb +20 -40
  197. data/lib/graphql/type_kinds.rb +7 -4
  198. data/lib/graphql/types/iso_8601_duration.rb +77 -0
  199. data/lib/graphql/types/relay/base_connection.rb +1 -1
  200. data/lib/graphql/types/relay/connection_behaviors.rb +68 -6
  201. data/lib/graphql/types/relay/edge_behaviors.rb +33 -5
  202. data/lib/graphql/types/relay/node_behaviors.rb +8 -2
  203. data/lib/graphql/types/relay/page_info_behaviors.rb +11 -2
  204. data/lib/graphql/types/relay.rb +0 -1
  205. data/lib/graphql/types/string.rb +1 -1
  206. data/lib/graphql/types.rb +1 -0
  207. data/lib/graphql/version.rb +1 -1
  208. data/lib/graphql.rb +27 -20
  209. data/readme.md +13 -3
  210. metadata +96 -47
  211. data/lib/graphql/analysis/ast/analyzer.rb +0 -84
  212. data/lib/graphql/analysis/ast/field_usage.rb +0 -57
  213. data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -22
  214. data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
  215. data/lib/graphql/analysis/ast/query_complexity.rb +0 -230
  216. data/lib/graphql/analysis/ast/query_depth.rb +0 -55
  217. data/lib/graphql/analysis/ast/visitor.rb +0 -269
  218. data/lib/graphql/analysis/ast.rb +0 -81
  219. data/lib/graphql/deprecation.rb +0 -9
  220. data/lib/graphql/filter.rb +0 -53
  221. data/lib/graphql/language/lexer.rl +0 -280
  222. data/lib/graphql/language/parser.y +0 -554
  223. data/lib/graphql/language/token.rb +0 -34
  224. data/lib/graphql/schema/base_64_bp.rb +0 -26
  225. data/lib/graphql/schema/invalid_type_error.rb +0 -7
  226. data/lib/graphql/static_validation/type_stack.rb +0 -216
  227. data/lib/graphql/subscriptions/instrumentation.rb +0 -28
  228. data/lib/graphql/types/relay/default_relay.rb +0 -21
@@ -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,292 +40,424 @@ 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
- def print_schema_definition(schema)
135
- if (schema.query.nil? || schema.query == 'Query') &&
136
- (schema.mutation.nil? || schema.mutation == 'Mutation') &&
137
- (schema.subscription.nil? || schema.subscription == 'Subscription') &&
138
- (schema.directives.empty?)
222
+ def print_schema_definition(schema, extension: false)
223
+ has_conventional_names = (schema.query.nil? || schema.query == 'Query') &&
224
+ (schema.mutation.nil? || schema.mutation == 'Mutation') &&
225
+ (schema.subscription.nil? || schema.subscription == 'Subscription')
226
+
227
+ if has_conventional_names && schema.directives.empty?
139
228
  return
140
229
  end
141
230
 
142
- out = "schema".dup
231
+ extension ? print_string("extend schema") : print_string("schema")
232
+
143
233
  if schema.directives.any?
144
234
  schema.directives.each do |dir|
145
- out << "\n "
146
- out << print_node(dir)
235
+ print_string("\n ")
236
+ print_node(dir)
237
+ end
238
+
239
+ if !has_conventional_names
240
+ print_string("\n")
147
241
  end
148
- out << "\n{"
149
- else
150
- out << " {\n"
151
242
  end
152
- out << " query: #{schema.query}\n" if schema.query
153
- out << " mutation: #{schema.mutation}\n" if schema.mutation
154
- out << " subscription: #{schema.subscription}\n" if schema.subscription
155
- out << "}"
243
+
244
+ if !has_conventional_names
245
+ if schema.directives.empty?
246
+ print_string(" ")
247
+ end
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("}")
253
+ end
156
254
  end
157
255
 
158
- def print_scalar_type_definition(scalar_type)
159
- out = print_description(scalar_type)
160
- out << "scalar #{scalar_type.name}"
161
- out << print_directives(scalar_type.directives)
256
+
257
+ def print_scalar_type_definition(scalar_type, extension: false)
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)
162
262
  end
163
263
 
164
- def print_object_type_definition(object_type)
165
- out = print_description(object_type)
166
- out << "type #{object_type.name}"
167
- out << print_implements(object_type) unless object_type.interfaces.empty?
168
- out << print_directives(object_type.directives)
169
- out << print_field_definitions(object_type.fields)
264
+ def print_object_type_definition(object_type, extension: false)
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)
170
271
  end
171
272
 
172
273
  def print_implements(type)
173
- " 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
174
283
  end
175
284
 
176
285
  def print_input_value_definition(input_value)
177
- out = "#{input_value.name}: #{print_node(input_value.type)}".dup
178
- out << " = #{print_node(input_value.default_value)}" unless input_value.default_value.nil?
179
- 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)
180
294
  end
181
295
 
182
296
  def print_arguments(arguments, indent: "")
183
- if arguments.all?{ |arg| !arg.description }
184
- 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
185
305
  end
186
306
 
187
- out = "(\n".dup
188
- out << arguments.map.with_index{ |arg, i|
189
- "#{print_description(arg, indent: " " + indent, first_in_block: i == 0)} #{indent}"\
190
- "#{print_input_value_definition(arg)}"
191
- }.join("\n")
192
- 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(")")
193
318
  end
194
319
 
195
320
  def print_field_definition(field)
196
- out = field.name.dup
321
+ print_string(field.name)
197
322
  unless field.arguments.empty?
198
- out << print_arguments(field.arguments, indent: " ")
323
+ print_arguments(field.arguments, indent: " ")
324
+ end
325
+ print_string(": ")
326
+ print_node(field.type)
327
+ print_directives(field.directives)
328
+ end
329
+
330
+ def print_interface_type_definition(interface_type, extension: false)
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)
337
+ end
338
+
339
+ def print_union_type_definition(union_type, extension: false)
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
199
354
  end
200
- out << ": #{print_node(field.type)}"
201
- out << print_directives(field.directives)
202
- end
203
-
204
- def print_interface_type_definition(interface_type)
205
- out = print_description(interface_type)
206
- out << "interface #{interface_type.name}"
207
- out << print_implements(interface_type) if interface_type.interfaces.any?
208
- out << print_directives(interface_type.directives)
209
- out << print_field_definitions(interface_type.fields)
210
- end
211
-
212
- def print_union_type_definition(union_type)
213
- out = print_description(union_type)
214
- out << "union #{union_type.name}"
215
- out << print_directives(union_type.directives)
216
- out << " = " + union_type.types.map(&:name).join(" | ")
217
355
  end
218
356
 
219
- def print_enum_type_definition(enum_type)
220
- out = print_description(enum_type)
221
- out << "enum #{enum_type.name}#{print_directives(enum_type.directives)} {\n"
222
- enum_type.values.each.with_index do |value, i|
223
- out << print_description(value, indent: ' ', first_in_block: i == 0)
224
- out << print_enum_value_definition(value)
357
+ def print_enum_type_definition(enum_type, extension: false)
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("}")
225
369
  end
226
- out << "}"
227
370
  end
228
371
 
229
372
  def print_enum_value_definition(enum_value)
230
- out = " #{enum_value.name}".dup
231
- out << print_directives(enum_value.directives)
232
- out << "\n"
373
+ print_string(" ")
374
+ print_string(enum_value.name)
375
+ print_directives(enum_value.directives)
376
+ print_string("\n")
233
377
  end
234
378
 
235
- def print_input_object_type_definition(input_object_type)
236
- out = print_description(input_object_type)
237
- out << "input #{input_object_type.name}"
238
- out << print_directives(input_object_type.directives)
379
+ def print_input_object_type_definition(input_object_type, extension: false)
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)
239
384
  if !input_object_type.fields.empty?
240
- out << " {\n"
385
+ print_string(" {\n")
241
386
  input_object_type.fields.each.with_index do |field, i|
242
- out << print_description(field, indent: ' ', first_in_block: i == 0)
243
- 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")
244
391
  end
245
- out << "}"
392
+ print_string("}")
246
393
  end
247
- out
248
394
  end
249
395
 
250
396
  def print_directive_definition(directive)
251
- out = print_description(directive)
252
- out << "directive @#{directive.name}"
397
+ print_description(directive)
398
+ print_string("directive @")
399
+ print_string(directive.name)
253
400
 
254
401
  if directive.arguments.any?
255
- out << print_arguments(directive.arguments)
402
+ print_arguments(directive.arguments)
256
403
  end
257
404
 
258
405
  if directive.repeatable
259
- out << " repeatable"
406
+ print_string(" repeatable")
260
407
  end
261
408
 
262
- 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
263
418
  end
264
419
 
265
420
  def print_description(node, indent: "", first_in_block: true)
266
- return ''.dup unless node.description
421
+ return unless node.description
267
422
 
268
- description = indent != '' && !first_in_block ? "\n".dup : "".dup
269
- 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))
270
425
  end
271
426
 
272
427
  def print_field_definitions(fields)
273
- if fields.empty?
274
- ""
275
- else
276
- out = " {\n".dup
277
- fields.each.with_index do |field, i|
278
- out << print_description(field, indent: ' ', first_in_block: i == 0)
279
- out << " #{print_field_definition(field)}\n"
280
- end
281
- 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
282
438
  end
439
+ print_string("}")
283
440
  end
284
441
 
285
442
  def print_directives(directives)
286
- if directives.any?
287
- directives.map { |d| " #{print_directive(d)}" }.join
288
- else
289
- ""
443
+ return if directives.empty?
444
+
445
+ directives.each do |d|
446
+ print_string(" ")
447
+ print_directive(d)
290
448
  end
291
449
  end
292
450
 
293
451
  def print_selections(selections, indent: "")
294
- if selections.any?
295
- out = " {\n".dup
296
- selections.each do |selection|
297
- out << print_node(selection, indent: indent + " ") << "\n"
298
- end
299
- out << "#{indent}}"
300
- else
301
- ""
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")
302
458
  end
459
+ print_string(indent)
460
+ print_string("}")
303
461
  end
304
462
 
305
463
  def print_node(node, indent: "")
@@ -338,40 +496,62 @@ module GraphQL
338
496
  print_variable_identifier(node)
339
497
  when Nodes::SchemaDefinition
340
498
  print_schema_definition(node)
499
+ when Nodes::SchemaExtension
500
+ print_schema_definition(node, extension: true)
341
501
  when Nodes::ScalarTypeDefinition
342
502
  print_scalar_type_definition(node)
503
+ when Nodes::ScalarTypeExtension
504
+ print_scalar_type_definition(node, extension: true)
343
505
  when Nodes::ObjectTypeDefinition
344
506
  print_object_type_definition(node)
507
+ when Nodes::ObjectTypeExtension
508
+ print_object_type_definition(node, extension: true)
345
509
  when Nodes::InputValueDefinition
346
510
  print_input_value_definition(node)
347
511
  when Nodes::FieldDefinition
348
512
  print_field_definition(node)
349
513
  when Nodes::InterfaceTypeDefinition
350
514
  print_interface_type_definition(node)
515
+ when Nodes::InterfaceTypeExtension
516
+ print_interface_type_definition(node, extension: true)
351
517
  when Nodes::UnionTypeDefinition
352
518
  print_union_type_definition(node)
519
+ when Nodes::UnionTypeExtension
520
+ print_union_type_definition(node, extension: true)
353
521
  when Nodes::EnumTypeDefinition
354
522
  print_enum_type_definition(node)
523
+ when Nodes::EnumTypeExtension
524
+ print_enum_type_definition(node, extension: true)
355
525
  when Nodes::EnumValueDefinition
356
526
  print_enum_value_definition(node)
357
527
  when Nodes::InputObjectTypeDefinition
358
528
  print_input_object_type_definition(node)
529
+ when Nodes::InputObjectTypeExtension
530
+ print_input_object_type_definition(node, extension: true)
359
531
  when Nodes::DirectiveDefinition
360
532
  print_directive_definition(node)
361
533
  when FalseClass, Float, Integer, NilClass, String, TrueClass, Symbol
362
- GraphQL::Language.serialize(node)
534
+ print_string(GraphQL::Language.serialize(node))
363
535
  when Array
364
- "[#{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("]")
365
542
  when Hash
366
- "{#{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("}")
367
551
  else
368
- GraphQL::Language.serialize(node.to_s)
552
+ print_string(GraphQL::Language.serialize(node.to_s))
369
553
  end
370
554
  end
371
-
372
- private
373
-
374
- attr_reader :node
375
555
  end
376
556
  end
377
557
  end