graphql 1.11.6 → 1.13.19

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 (293) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +3 -8
  3. data/lib/generators/graphql/enum_generator.rb +4 -10
  4. data/lib/generators/graphql/field_extractor.rb +31 -0
  5. data/lib/generators/graphql/input_generator.rb +50 -0
  6. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  7. data/lib/generators/graphql/install_generator.rb +17 -7
  8. data/lib/generators/graphql/interface_generator.rb +7 -7
  9. data/lib/generators/graphql/loader_generator.rb +1 -0
  10. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  11. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  12. data/lib/generators/graphql/mutation_generator.rb +6 -30
  13. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  14. data/lib/generators/graphql/object_generator.rb +12 -38
  15. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  16. data/lib/generators/graphql/relay.rb +63 -0
  17. data/lib/generators/graphql/relay_generator.rb +21 -0
  18. data/lib/generators/graphql/scalar_generator.rb +4 -2
  19. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  20. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  21. data/lib/generators/graphql/templates/enum.erb +5 -1
  22. data/lib/generators/graphql/templates/graphql_controller.erb +2 -2
  23. data/lib/generators/graphql/templates/input.erb +9 -0
  24. data/lib/generators/graphql/templates/interface.erb +4 -2
  25. data/lib/generators/graphql/templates/mutation.erb +1 -1
  26. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  27. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  28. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  29. data/lib/generators/graphql/templates/node_type.erb +9 -0
  30. data/lib/generators/graphql/templates/object.erb +5 -3
  31. data/lib/generators/graphql/templates/query_type.erb +1 -3
  32. data/lib/generators/graphql/templates/scalar.erb +3 -1
  33. data/lib/generators/graphql/templates/schema.erb +19 -34
  34. data/lib/generators/graphql/templates/union.erb +4 -2
  35. data/lib/generators/graphql/type_generator.rb +47 -10
  36. data/lib/generators/graphql/union_generator.rb +5 -5
  37. data/lib/graphql/analysis/analyze_query.rb +7 -0
  38. data/lib/graphql/analysis/ast/field_usage.rb +28 -1
  39. data/lib/graphql/analysis/ast/query_complexity.rb +10 -14
  40. data/lib/graphql/analysis/ast/visitor.rb +14 -5
  41. data/lib/graphql/analysis/ast.rb +11 -2
  42. data/lib/graphql/argument.rb +1 -1
  43. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  44. data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
  45. data/lib/graphql/backtrace/table.rb +34 -3
  46. data/lib/graphql/backtrace/traced_error.rb +0 -1
  47. data/lib/graphql/backtrace/tracer.rb +40 -10
  48. data/lib/graphql/backtrace.rb +28 -19
  49. data/lib/graphql/backwards_compatibility.rb +2 -1
  50. data/lib/graphql/base_type.rb +6 -4
  51. data/lib/graphql/boolean_type.rb +1 -1
  52. data/lib/graphql/compatibility/execution_specification.rb +1 -0
  53. data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
  54. data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
  55. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
  56. data/lib/graphql/dataloader/null_dataloader.rb +22 -0
  57. data/lib/graphql/dataloader/request.rb +19 -0
  58. data/lib/graphql/dataloader/request_all.rb +19 -0
  59. data/lib/graphql/dataloader/source.rb +155 -0
  60. data/lib/graphql/dataloader.rb +308 -0
  61. data/lib/graphql/date_encoding_error.rb +16 -0
  62. data/lib/graphql/define/assign_global_id_field.rb +1 -1
  63. data/lib/graphql/define/instance_definable.rb +48 -3
  64. data/lib/graphql/define/type_definer.rb +5 -5
  65. data/lib/graphql/deprecated_dsl.rb +18 -5
  66. data/lib/graphql/deprecation.rb +9 -0
  67. data/lib/graphql/directive/deprecated_directive.rb +1 -1
  68. data/lib/graphql/directive/include_directive.rb +1 -1
  69. data/lib/graphql/directive/skip_directive.rb +1 -1
  70. data/lib/graphql/directive.rb +1 -5
  71. data/lib/graphql/enum_type.rb +9 -3
  72. data/lib/graphql/execution/errors.rb +110 -7
  73. data/lib/graphql/execution/execute.rb +8 -1
  74. data/lib/graphql/execution/interpreter/arguments.rb +57 -5
  75. data/lib/graphql/execution/interpreter/arguments_cache.rb +49 -15
  76. data/lib/graphql/execution/interpreter/handles_raw_value.rb +0 -7
  77. data/lib/graphql/execution/interpreter/resolve.rb +37 -25
  78. data/lib/graphql/execution/interpreter/runtime.rb +670 -294
  79. data/lib/graphql/execution/interpreter.rb +16 -16
  80. data/lib/graphql/execution/lazy.rb +5 -1
  81. data/lib/graphql/execution/lookahead.rb +2 -2
  82. data/lib/graphql/execution/multiplex.rb +39 -23
  83. data/lib/graphql/field.rb +1 -1
  84. data/lib/graphql/float_type.rb +1 -1
  85. data/lib/graphql/function.rb +4 -0
  86. data/lib/graphql/id_type.rb +1 -1
  87. data/lib/graphql/input_object_type.rb +3 -1
  88. data/lib/graphql/int_type.rb +1 -1
  89. data/lib/graphql/integer_decoding_error.rb +17 -0
  90. data/lib/graphql/integer_encoding_error.rb +18 -2
  91. data/lib/graphql/interface_type.rb +4 -2
  92. data/lib/graphql/internal_representation/document.rb +2 -2
  93. data/lib/graphql/internal_representation/rewrite.rb +1 -1
  94. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  95. data/lib/graphql/introspection/directive_type.rb +11 -5
  96. data/lib/graphql/introspection/entry_points.rb +2 -2
  97. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  98. data/lib/graphql/introspection/field_type.rb +3 -3
  99. data/lib/graphql/introspection/input_value_type.rb +10 -4
  100. data/lib/graphql/introspection/schema_type.rb +10 -5
  101. data/lib/graphql/introspection/type_type.rb +18 -12
  102. data/lib/graphql/introspection.rb +5 -2
  103. data/lib/graphql/invalid_null_error.rb +1 -1
  104. data/lib/graphql/language/block_string.rb +2 -6
  105. data/lib/graphql/language/cache.rb +37 -0
  106. data/lib/graphql/language/document_from_schema_definition.rb +60 -26
  107. data/lib/graphql/language/lexer.rb +50 -28
  108. data/lib/graphql/language/lexer.rl +2 -4
  109. data/lib/graphql/language/nodes.rb +14 -4
  110. data/lib/graphql/language/parser.rb +856 -825
  111. data/lib/graphql/language/parser.y +28 -11
  112. data/lib/graphql/language/printer.rb +10 -1
  113. data/lib/graphql/language/sanitized_printer.rb +5 -5
  114. data/lib/graphql/language/token.rb +0 -4
  115. data/lib/graphql/language.rb +1 -0
  116. data/lib/graphql/name_validator.rb +0 -4
  117. data/lib/graphql/object_type.rb +4 -4
  118. data/lib/graphql/pagination/active_record_relation_connection.rb +47 -3
  119. data/lib/graphql/pagination/connection.rb +19 -1
  120. data/lib/graphql/pagination/connections.rb +45 -30
  121. data/lib/graphql/pagination/relation_connection.rb +69 -28
  122. data/lib/graphql/parse_error.rb +0 -1
  123. data/lib/graphql/query/arguments.rb +2 -2
  124. data/lib/graphql/query/arguments_cache.rb +1 -2
  125. data/lib/graphql/query/context.rb +22 -4
  126. data/lib/graphql/query/executor.rb +0 -1
  127. data/lib/graphql/query/input_validation_result.rb +9 -0
  128. data/lib/graphql/query/literal_input.rb +1 -1
  129. data/lib/graphql/query/null_context.rb +21 -9
  130. data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
  131. data/lib/graphql/query/serial_execution.rb +1 -0
  132. data/lib/graphql/query/validation_pipeline.rb +3 -4
  133. data/lib/graphql/query/variable_validation_error.rb +3 -3
  134. data/lib/graphql/query/variables.rb +35 -4
  135. data/lib/graphql/query.rb +20 -8
  136. data/lib/graphql/railtie.rb +9 -1
  137. data/lib/graphql/rake_task.rb +3 -0
  138. data/lib/graphql/relay/array_connection.rb +2 -2
  139. data/lib/graphql/relay/base_connection.rb +7 -0
  140. data/lib/graphql/relay/connection_instrumentation.rb +4 -4
  141. data/lib/graphql/relay/connection_type.rb +16 -3
  142. data/lib/graphql/relay/edges_instrumentation.rb +0 -1
  143. data/lib/graphql/relay/global_id_resolve.rb +1 -2
  144. data/lib/graphql/relay/mutation.rb +2 -1
  145. data/lib/graphql/relay/node.rb +3 -0
  146. data/lib/graphql/relay/page_info.rb +1 -1
  147. data/lib/graphql/relay/range_add.rb +14 -5
  148. data/lib/graphql/relay/type_extensions.rb +2 -0
  149. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  150. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  151. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  152. data/lib/graphql/rubocop.rb +4 -0
  153. data/lib/graphql/scalar_type.rb +3 -1
  154. data/lib/graphql/schema/addition.rb +247 -0
  155. data/lib/graphql/schema/argument.rb +177 -21
  156. data/lib/graphql/schema/build_from_definition.rb +150 -55
  157. data/lib/graphql/schema/default_type_error.rb +2 -0
  158. data/lib/graphql/schema/directive/feature.rb +1 -1
  159. data/lib/graphql/schema/directive/flagged.rb +57 -0
  160. data/lib/graphql/schema/directive/include.rb +1 -1
  161. data/lib/graphql/schema/directive/skip.rb +1 -1
  162. data/lib/graphql/schema/directive/transform.rb +14 -2
  163. data/lib/graphql/schema/directive.rb +103 -4
  164. data/lib/graphql/schema/enum.rb +72 -11
  165. data/lib/graphql/schema/enum_value.rb +18 -6
  166. data/lib/graphql/schema/field/connection_extension.rb +4 -2
  167. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  168. data/lib/graphql/schema/field.rb +332 -111
  169. data/lib/graphql/schema/field_extension.rb +89 -2
  170. data/lib/graphql/schema/find_inherited_value.rb +4 -1
  171. data/lib/graphql/schema/finder.rb +5 -5
  172. data/lib/graphql/schema/input_object.rb +79 -55
  173. data/lib/graphql/schema/interface.rb +12 -20
  174. data/lib/graphql/schema/introspection_system.rb +1 -1
  175. data/lib/graphql/schema/list.rb +21 -4
  176. data/lib/graphql/schema/loader.rb +11 -0
  177. data/lib/graphql/schema/member/accepts_definition.rb +15 -3
  178. data/lib/graphql/schema/member/base_dsl_methods.rb +5 -16
  179. data/lib/graphql/schema/member/build_type.rb +4 -7
  180. data/lib/graphql/schema/member/cached_graphql_definition.rb +29 -2
  181. data/lib/graphql/schema/member/has_arguments.rb +166 -74
  182. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  183. data/lib/graphql/schema/member/has_directives.rb +98 -0
  184. data/lib/graphql/schema/member/has_fields.rb +77 -22
  185. data/lib/graphql/schema/member/has_interfaces.rb +100 -0
  186. data/lib/graphql/schema/member/has_validators.rb +31 -0
  187. data/lib/graphql/schema/member/instrumentation.rb +0 -1
  188. data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
  189. data/lib/graphql/schema/member/validates_input.rb +2 -2
  190. data/lib/graphql/schema/member.rb +5 -0
  191. data/lib/graphql/schema/middleware_chain.rb +1 -1
  192. data/lib/graphql/schema/non_null.rb +9 -3
  193. data/lib/graphql/schema/object.rb +40 -80
  194. data/lib/graphql/schema/printer.rb +16 -20
  195. data/lib/graphql/schema/relay_classic_mutation.rb +38 -4
  196. data/lib/graphql/schema/resolver/has_payload_type.rb +29 -2
  197. data/lib/graphql/schema/resolver.rb +110 -64
  198. data/lib/graphql/schema/scalar.rb +18 -2
  199. data/lib/graphql/schema/subscription.rb +55 -9
  200. data/lib/graphql/schema/timeout_middleware.rb +3 -1
  201. data/lib/graphql/schema/traversal.rb +1 -1
  202. data/lib/graphql/schema/type_expression.rb +1 -1
  203. data/lib/graphql/schema/type_membership.rb +18 -4
  204. data/lib/graphql/schema/union.rb +8 -1
  205. data/lib/graphql/schema/validation.rb +4 -2
  206. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  207. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  208. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  209. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  210. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  211. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  212. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  213. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  214. data/lib/graphql/schema/validator.rb +171 -0
  215. data/lib/graphql/schema/warden.rb +126 -53
  216. data/lib/graphql/schema.rb +262 -281
  217. data/lib/graphql/static_validation/all_rules.rb +2 -0
  218. data/lib/graphql/static_validation/base_visitor.rb +9 -6
  219. data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
  220. data/lib/graphql/static_validation/error.rb +3 -1
  221. data/lib/graphql/static_validation/literal_validator.rb +1 -1
  222. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +4 -2
  223. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +6 -2
  224. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
  225. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  226. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
  227. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
  228. data/lib/graphql/static_validation/rules/fields_will_merge.rb +90 -47
  229. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  230. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  231. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  232. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  233. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  234. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  235. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -2
  236. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
  237. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
  238. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +14 -8
  239. data/lib/graphql/static_validation/validation_context.rb +12 -2
  240. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  241. data/lib/graphql/static_validation/validator.rb +41 -10
  242. data/lib/graphql/static_validation.rb +1 -0
  243. data/lib/graphql/string_encoding_error.rb +13 -3
  244. data/lib/graphql/string_type.rb +1 -1
  245. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +39 -8
  246. data/lib/graphql/subscriptions/broadcast_analyzer.rb +0 -3
  247. data/lib/graphql/subscriptions/event.rb +68 -32
  248. data/lib/graphql/subscriptions/instrumentation.rb +0 -1
  249. data/lib/graphql/subscriptions/serialize.rb +34 -5
  250. data/lib/graphql/subscriptions/subscription_root.rb +1 -1
  251. data/lib/graphql/subscriptions.rb +34 -39
  252. data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -21
  253. data/lib/graphql/tracing/appoptics_tracing.rb +3 -1
  254. data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
  255. data/lib/graphql/tracing/data_dog_tracing.rb +24 -2
  256. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  257. data/lib/graphql/tracing/platform_tracing.rb +24 -12
  258. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  259. data/lib/graphql/tracing/skylight_tracing.rb +1 -1
  260. data/lib/graphql/tracing.rb +2 -2
  261. data/lib/graphql/types/big_int.rb +5 -1
  262. data/lib/graphql/types/int.rb +10 -3
  263. data/lib/graphql/types/iso_8601_date.rb +13 -5
  264. data/lib/graphql/types/iso_8601_date_time.rb +8 -1
  265. data/lib/graphql/types/relay/base_connection.rb +6 -91
  266. data/lib/graphql/types/relay/base_edge.rb +2 -34
  267. data/lib/graphql/types/relay/connection_behaviors.rb +174 -0
  268. data/lib/graphql/types/relay/default_relay.rb +31 -0
  269. data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
  270. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  271. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  272. data/lib/graphql/types/relay/node.rb +2 -4
  273. data/lib/graphql/types/relay/node_behaviors.rb +15 -0
  274. data/lib/graphql/types/relay/node_field.rb +3 -22
  275. data/lib/graphql/types/relay/nodes_field.rb +16 -18
  276. data/lib/graphql/types/relay/page_info.rb +2 -14
  277. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  278. data/lib/graphql/types/relay.rb +11 -3
  279. data/lib/graphql/types/string.rb +8 -2
  280. data/lib/graphql/unauthorized_error.rb +1 -1
  281. data/lib/graphql/union_type.rb +3 -1
  282. data/lib/graphql/upgrader/member.rb +1 -0
  283. data/lib/graphql/upgrader/schema.rb +1 -0
  284. data/lib/graphql/version.rb +1 -1
  285. data/lib/graphql.rb +68 -37
  286. data/readme.md +3 -6
  287. metadata +83 -113
  288. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  289. data/lib/graphql/types/relay/base_field.rb +0 -22
  290. data/lib/graphql/types/relay/base_interface.rb +0 -29
  291. data/lib/graphql/types/relay/base_object.rb +0 -26
  292. /data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +0 -0
  293. /data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +0 -0
@@ -1,6 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # test_via: ../execution/execute.rb
3
- # test_via: ../execution/lazy.rb
4
2
  module GraphQL
5
3
  class Query
6
4
  # Expose some query-specific info to field resolve functions.
@@ -158,6 +156,15 @@ module GraphQL
158
156
  @scoped_context = {}
159
157
  end
160
158
 
159
+ # @return [Hash] A hash that will be added verbatim to the result hash, as `"extensions" => { ... }`
160
+ def response_extensions
161
+ namespace(:__query_result_extensions__)
162
+ end
163
+
164
+ def dataloader
165
+ @dataloader ||= self[:dataloader] || (query.multiplex ? query.multiplex.dataloader : schema.dataloader_class.new)
166
+ end
167
+
161
168
  # @api private
162
169
  attr_writer :interpreter
163
170
 
@@ -167,7 +174,10 @@ module GraphQL
167
174
  # @api private
168
175
  attr_accessor :scoped_context
169
176
 
170
- def_delegators :@provided_values, :[]=
177
+ def []=(key, value)
178
+ @provided_values[key] = value
179
+ end
180
+
171
181
  def_delegators :@query, :trace, :interpreter?
172
182
 
173
183
  # @!method []=(key, value)
@@ -218,9 +228,12 @@ module GraphQL
218
228
 
219
229
  # @return [GraphQL::Schema::Warden]
220
230
  def warden
221
- @warden ||= @query.warden
231
+ @warden ||= (@query && @query.warden)
222
232
  end
223
233
 
234
+ # @api private
235
+ attr_writer :warden
236
+
224
237
  # Get an isolated hash for `ns`. Doesn't affect user-provided storage.
225
238
  # @param ns [Object] a usage-specific namespace identifier
226
239
  # @return [Hash] namespaced storage
@@ -228,6 +241,11 @@ module GraphQL
228
241
  @storage[ns]
229
242
  end
230
243
 
244
+ # @return [Boolean] true if this namespace was accessed before
245
+ def namespace?(ns)
246
+ @storage.key?(ns)
247
+ end
248
+
231
249
  def inspect
232
250
  "#<Query::Context ...>"
233
251
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # test_via: ../query.rb
3
2
  module GraphQL
4
3
  class Query
5
4
  class Executor
@@ -4,6 +4,12 @@ module GraphQL
4
4
  class InputValidationResult
5
5
  attr_accessor :problems
6
6
 
7
+ def self.from_problem(explanation, path = nil, extensions: nil, message: nil)
8
+ result = self.new
9
+ result.add_problem(explanation, path, extensions: extensions, message: message)
10
+ result
11
+ end
12
+
7
13
  def initialize(valid: true, problems: nil)
8
14
  @valid = valid
9
15
  @problems = problems
@@ -38,6 +44,9 @@ module GraphQL
38
44
  # It could have been explicitly set on inner_result (if it had no problems)
39
45
  @valid = false
40
46
  end
47
+
48
+ VALID = self.new
49
+ VALID.freeze
41
50
  end
42
51
  end
43
52
  end
@@ -62,7 +62,7 @@ module GraphQL
62
62
  raise ArgumentError, "Unexpected ast_arguments: #{ast_arguments}"
63
63
  end
64
64
 
65
- argument_defns = argument_owner.arguments
65
+ argument_defns = argument_owner.arguments(context || GraphQL::Query::NullContext)
66
66
  argument_defns.each do |arg_name, arg_defn|
67
67
  ast_arg = indexed_arguments[arg_name]
68
68
  # First, check the argument in the AST.
@@ -4,16 +4,28 @@ module GraphQL
4
4
  # This object can be `ctx` in places where there is no query
5
5
  class NullContext
6
6
  class NullWarden < GraphQL::Schema::Warden
7
- def visible?(t); true; end
8
- def visible_field?(t); true; end
9
- def visible_type?(t); true; end
7
+ def visible_field?(field, ctx); true; end
8
+ def visible_argument?(arg, ctx); true; end
9
+ def visible_type?(type, ctx); true; end
10
+ def visible_enum_value?(ev, ctx); true; end
11
+ def visible_type_membership?(tm, ctx); true; end
10
12
  end
11
13
 
12
- attr_reader :schema, :query, :warden
14
+ class NullQuery
15
+ def with_error_handling
16
+ yield
17
+ end
18
+ end
19
+
20
+ class NullSchema < GraphQL::Schema
21
+ end
22
+
23
+ attr_reader :schema, :query, :warden, :dataloader
13
24
 
14
25
  def initialize
15
- @query = nil
16
- @schema = GraphQL::Schema.new
26
+ @query = NullQuery.new
27
+ @dataloader = GraphQL::Dataloader::NullDataloader.new
28
+ @schema = NullSchema
17
29
  @warden = NullWarden.new(
18
30
  GraphQL::Filter.new,
19
31
  context: self,
@@ -24,7 +36,7 @@ module GraphQL
24
36
  def [](key); end
25
37
 
26
38
  def interpreter?
27
- false
39
+ true
28
40
  end
29
41
 
30
42
  class << self
@@ -33,10 +45,10 @@ module GraphQL
33
45
  def [](key); end
34
46
 
35
47
  def instance
36
- @instance = self.new
48
+ @instance ||= self.new
37
49
  end
38
50
 
39
- def_delegators :instance, :query, :schema, :warden, :interpreter?
51
+ def_delegators :instance, :query, :warden, :schema, :interpreter?, :dataloader
40
52
  end
41
53
  end
42
54
  end
@@ -81,7 +81,7 @@ module GraphQL
81
81
  # is added to the "errors" key.
82
82
  def get_raw_value
83
83
  begin
84
- @field_ctx.schema.middleware.invoke([parent_type, target, field, arguments, @field_ctx])
84
+ @field_ctx.schema.middleware.invoke([parent_type, target, field, arguments, @field_ctx]) # rubocop:disable Development/ContextIsPassedCop -- unrelated
85
85
  rescue GraphQL::ExecutionError => err
86
86
  err
87
87
  end
@@ -16,6 +16,7 @@ module GraphQL
16
16
  # @param query_object [GraphQL::Query] the query object for this execution
17
17
  # @return [Hash] a spec-compliant GraphQL result, as a hash
18
18
  def execute(ast_operation, root_type, query_object)
19
+ GraphQL::Deprecation.warn "#{self.class} will be removed in GraphQL-Ruby 2.0, please upgrade to the Interpreter: https://graphql-ruby.org/queries/interpreter.html"
19
20
  operation_resolution.resolve(
20
21
  query_object.irep_selection,
21
22
  root_type,
@@ -16,10 +16,9 @@ module GraphQL
16
16
  class ValidationPipeline
17
17
  attr_reader :max_depth, :max_complexity
18
18
 
19
- def initialize(query:, validate:, parse_error:, operation_name_error:, max_depth:, max_complexity:)
19
+ def initialize(query:, parse_error:, operation_name_error:, max_depth:, max_complexity:)
20
20
  @validation_errors = []
21
21
  @internal_representation = nil
22
- @validate = validate
23
22
  @parse_error = parse_error
24
23
  @operation_name_error = operation_name_error
25
24
  @query = query
@@ -36,7 +35,7 @@ module GraphQL
36
35
  @valid
37
36
  end
38
37
 
39
- # @return [Array<GraphQL::StaticValidation::Error >] Static validation errors for the query string
38
+ # @return [Array<GraphQL::StaticValidation::Error, GraphQL::Query::VariableValidationError>] Static validation errors for the query string
40
39
  def validation_errors
41
40
  ensure_has_validated
42
41
  @validation_errors
@@ -72,7 +71,7 @@ module GraphQL
72
71
  elsif @operation_name_error
73
72
  @validation_errors << @operation_name_error
74
73
  else
75
- validation_result = @schema.static_validator.validate(@query, validate: @validate)
74
+ validation_result = @schema.static_validator.validate(@query, validate: @query.validate, timeout: @schema.validate_timeout, max_errors: @schema.validate_max_errors)
76
75
  @validation_errors.concat(validation_result[:errors])
77
76
  @internal_representation = validation_result[:irep]
78
77
 
@@ -4,11 +4,11 @@ module GraphQL
4
4
  class VariableValidationError < GraphQL::ExecutionError
5
5
  attr_accessor :value, :validation_result
6
6
 
7
- def initialize(variable_ast, type, value, validation_result)
7
+ def initialize(variable_ast, type, value, validation_result, msg: nil)
8
8
  @value = value
9
9
  @validation_result = validation_result
10
10
 
11
- msg = "Variable $#{variable_ast.name} of type #{type.to_type_signature} was provided invalid value"
11
+ msg ||= "Variable $#{variable_ast.name} of type #{type.to_type_signature} was provided invalid value"
12
12
 
13
13
  if problem_fields.any?
14
14
  msg += " for #{problem_fields.join(", ")}"
@@ -23,7 +23,7 @@ module GraphQL
23
23
  # a one level deep merge explicitly. However beyond that only show the
24
24
  # latest value and problems.
25
25
  super.merge({ "extensions" => { "value" => value, "problems" => validation_result.problems }}) do |key, oldValue, newValue|
26
- if oldValue.respond_to? merge
26
+ if oldValue.respond_to?(:merge)
27
27
  oldValue.merge(newValue)
28
28
  else
29
29
  newValue
@@ -17,6 +17,10 @@ module GraphQL
17
17
  @provided_variables = GraphQL::Argument.deep_stringify(provided_variables)
18
18
  @errors = []
19
19
  @storage = ast_variables.each_with_object({}) do |ast_variable, memo|
20
+ if schema.validate_max_errors && schema.validate_max_errors <= @errors.count
21
+ add_max_errors_reached_message
22
+ break
23
+ end
20
24
  # Find the right value for this variable:
21
25
  # - First, use the value provided at runtime
22
26
  # - Then, fall back to the default value from the query string
@@ -29,8 +33,9 @@ module GraphQL
29
33
  default_value = ast_variable.default_value
30
34
  provided_value = @provided_variables[variable_name]
31
35
  value_was_provided = @provided_variables.key?(variable_name)
36
+ max_errors = schema.validate_max_errors - @errors.count if schema.validate_max_errors
32
37
  begin
33
- validation_result = variable_type.validate_input(provided_value, ctx)
38
+ validation_result = variable_type.validate_input(provided_value, ctx, max_errors: max_errors)
34
39
  if validation_result.valid?
35
40
  if value_was_provided
36
41
  # Add the variable if a value was provided
@@ -45,7 +50,11 @@ module GraphQL
45
50
  end
46
51
  elsif default_value != nil
47
52
  memo[variable_name] = if ctx.interpreter?
48
- default_value
53
+ if default_value.is_a?(Language::Nodes::NullValue)
54
+ nil
55
+ else
56
+ default_value
57
+ end
49
58
  else
50
59
  # Add the variable if it wasn't provided but it has a default value (including `null`)
51
60
  GraphQL::Query::LiteralInput.coerce(variable_type, default_value, self)
@@ -57,8 +66,7 @@ module GraphQL
57
66
  # like InputValidationResults generated by validate_non_null_input but unfortunately we don't
58
67
  # have this information available in the coerce_input call chain. Note this path is the path
59
68
  # that appears under errors.extensions.problems.path and NOT the result path under errors.path.
60
- validation_result = GraphQL::Query::InputValidationResult.new
61
- validation_result.add_problem(ex.message)
69
+ validation_result = GraphQL::Query::InputValidationResult.from_problem(ex.message)
62
70
  end
63
71
 
64
72
  if !validation_result.valid?
@@ -69,6 +77,29 @@ module GraphQL
69
77
  end
70
78
 
71
79
  def_delegators :@storage, :length, :key?, :[], :fetch, :to_h
80
+
81
+ private
82
+
83
+ def deep_stringify(val)
84
+ case val
85
+ when Array
86
+ val.map { |v| deep_stringify(v) }
87
+ when Hash
88
+ new_val = {}
89
+ val.each do |k, v|
90
+ new_val[k.to_s] = deep_stringify(v)
91
+ end
92
+ new_val
93
+ else
94
+ val
95
+ end
96
+ end
97
+
98
+ def add_max_errors_reached_message
99
+ message = "Too many errors processing variables, max validation error limit reached. Execution aborted"
100
+ validation_result = GraphQL::Query::InputValidationResult.from_problem(message)
101
+ errors << GraphQL::Query::VariableValidationError.new(nil, nil, nil, validation_result, msg: message)
102
+ end
72
103
  end
73
104
  end
74
105
  end
data/lib/graphql/query.rb CHANGED
@@ -88,6 +88,7 @@ module GraphQL
88
88
  schema = schema.graphql_definition
89
89
  end
90
90
  @schema = schema
91
+ @interpreter = @schema.interpreter?
91
92
  @filter = schema.default_filter.merge(except: except, only: only)
92
93
  @context = schema.context_class.new(query: self, object: root_value, values: context)
93
94
  @warden = warden
@@ -116,6 +117,10 @@ module GraphQL
116
117
  raise ArgumentError, "Query should only be provided a query string or a document, not both."
117
118
  end
118
119
 
120
+ if @query_string && !@query_string.is_a?(String)
121
+ raise ArgumentError, "Query string argument should be a String, got #{@query_string.class.name} instead."
122
+ end
123
+
119
124
  # A two-layer cache of type resolution:
120
125
  # { abstract_type => { value => resolved_type } }
121
126
  @resolved_types_cache = Hash.new do |h1, k1|
@@ -148,7 +153,11 @@ module GraphQL
148
153
  @query_string ||= (document ? document.to_query_string : nil)
149
154
  end
150
155
 
151
- def_delegators :@schema, :interpreter?
156
+ def interpreter?
157
+ @interpreter
158
+ end
159
+
160
+ attr_accessor :multiplex
152
161
 
153
162
  def subscription_update?
154
163
  @subscription_topic && subscription?
@@ -190,9 +199,7 @@ module GraphQL
190
199
  # @return [Hash] A GraphQL response, with `"data"` and/or `"errors"` keys
191
200
  def result
192
201
  if !@executed
193
- with_prepared_ast {
194
- Execution::Multiplex.run_queries(@schema, [self], context: @context)
195
- }
202
+ Execution::Multiplex.run_queries(@schema, [self], context: @context)
196
203
  end
197
204
  @result ||= Query::Result.new(query: self, values: @result_values)
198
205
  end
@@ -246,12 +253,18 @@ module GraphQL
246
253
  # @param parent_object [GraphQL::Schema::Object]
247
254
  # @return Hash{Symbol => Object}
248
255
  def arguments_for(ast_node, definition, parent_object: nil)
256
+ if interpreter?
257
+ arguments_cache.fetch(ast_node, definition, parent_object)
258
+ else
259
+ arguments_cache[ast_node][definition]
260
+ end
261
+ end
262
+
263
+ def arguments_cache
249
264
  if interpreter?
250
265
  @arguments_cache ||= Execution::Interpreter::ArgumentsCache.new(self)
251
- @arguments_cache.fetch(ast_node, definition, parent_object)
252
266
  else
253
267
  @arguments_cache ||= ArgumentsCache.build(self)
254
- @arguments_cache[ast_node][definition]
255
268
  end
256
269
  end
257
270
 
@@ -261,7 +274,7 @@ module GraphQL
261
274
  # @return [String, nil] Returns nil if the query is invalid.
262
275
  def sanitized_query_string(inline_variables: true)
263
276
  with_prepared_ast {
264
- GraphQL::Language::SanitizedPrinter.new(self, inline_variables: inline_variables).sanitized_query_string
277
+ schema.sanitized_printer.new(self, inline_variables: inline_variables).sanitized_query_string
265
278
  }
266
279
  end
267
280
 
@@ -421,7 +434,6 @@ module GraphQL
421
434
 
422
435
  @validation_pipeline = GraphQL::Query::ValidationPipeline.new(
423
436
  query: self,
424
- validate: @validate,
425
437
  parse_error: parse_error,
426
438
  operation_name_error: operation_name_error,
427
439
  max_depth: @max_depth,
@@ -1,8 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
-
4
3
  module GraphQL
5
4
  class Railtie < Rails::Railtie
5
+ config.before_configuration do
6
+ # Bootsnap compile cache has similar expiration properties,
7
+ # so we assume that if the user has bootsnap setup it's ok
8
+ # to piggy back on it.
9
+ if ::Object.const_defined?("Bootsnap::CompileCache::ISeq") && Bootsnap::CompileCache::ISeq.cache_dir
10
+ Language::Parser.cache ||= Language::Cache.new(Pathname.new(Bootsnap::CompileCache::ISeq.cache_dir).join('graphql'))
11
+ end
12
+ end
13
+
6
14
  rake_tasks do
7
15
  # Defer this so that you only need the `parser` gem when you _run_ the upgrader
8
16
  def load_upgraders
@@ -98,6 +98,9 @@ module GraphQL
98
98
  result = schema.public_send(method_name, only: @only, except: @except, context: context)
99
99
  dir = File.dirname(file)
100
100
  FileUtils.mkdir_p(dir)
101
+ if !result.end_with?("\n")
102
+ result += "\n"
103
+ end
101
104
  File.write(file, result)
102
105
  end
103
106
 
@@ -31,8 +31,6 @@ module GraphQL
31
31
  end
32
32
  end
33
33
 
34
- private
35
-
36
34
  def first
37
35
  @first ||= begin
38
36
  capped = limit_pagination_argument(arguments[:first], max_page_size)
@@ -47,6 +45,8 @@ module GraphQL
47
45
  @last ||= limit_pagination_argument(arguments[:last], max_page_size)
48
46
  end
49
47
 
48
+ private
49
+
50
50
  # apply first / last limit results
51
51
  def paged_nodes
52
52
  @paged_nodes ||= begin
@@ -59,6 +59,13 @@ module GraphQL
59
59
  # @param parent [Object] The object which this collection belongs to
60
60
  # @param context [GraphQL::Query::Context] The context from the field being resolved
61
61
  def initialize(nodes, arguments, field: nil, max_page_size: nil, parent: nil, context: nil)
62
+ GraphQL::Deprecation.warn "GraphQL::Relay::BaseConnection (used for #{self.class}) will be removed from GraphQL-Ruby 2.0, use GraphQL::Pagination::Connections instead: https://graphql-ruby.org/pagination/overview.html"
63
+
64
+ deprecated_caller = caller(0, 10).find { |c| !c.include?("lib/graphql") }
65
+ if deprecated_caller
66
+ GraphQL::Deprecation.warn " -> called from #{deprecated_caller}"
67
+ end
68
+
62
69
  @context = context
63
70
  @nodes = nodes
64
71
  @arguments = arguments
@@ -10,10 +10,10 @@ module GraphQL
10
10
  def self.default_arguments
11
11
  @default_arguments ||= begin
12
12
  argument_definitions = [
13
- ["first", GraphQL::INT_TYPE, "Returns the first _n_ elements from the list."],
14
- ["after", GraphQL::STRING_TYPE, "Returns the elements in the list that come after the specified cursor."],
15
- ["last", GraphQL::INT_TYPE, "Returns the last _n_ elements from the list."],
16
- ["before", GraphQL::STRING_TYPE, "Returns the elements in the list that come before the specified cursor."],
13
+ ["first", GraphQL::DEPRECATED_INT_TYPE, "Returns the first _n_ elements from the list."],
14
+ ["after", GraphQL::DEPRECATED_STRING_TYPE, "Returns the elements in the list that come after the specified cursor."],
15
+ ["last", GraphQL::DEPRECATED_INT_TYPE, "Returns the last _n_ elements from the list."],
16
+ ["before", GraphQL::DEPRECATED_STRING_TYPE, "Returns the elements in the list that come before the specified cursor."],
17
17
  ]
18
18
 
19
19
  argument_definitions.reduce({}) do |memo, arg_defn|
@@ -5,9 +5,22 @@ module GraphQL
5
5
  module ConnectionType
6
6
  class << self
7
7
  # @return [Boolean] If true, connection types get a `nodes` shortcut field
8
- attr_accessor :default_nodes_field
8
+ def default_nodes_field=(new_setting)
9
+ if new_setting
10
+ warn("GraphQL::Relay::ConnectionType will be removed in GraphQL 2.0.0; migrate to `GraphQL::Pagination::Connections` and remove this setting (`default_nodes_field = true`).")
11
+ end
12
+ @default_nodes_field = new_setting
13
+ end
14
+ attr_reader :default_nodes_field
15
+
9
16
  # @return [Boolean] If true, connections check for reverse-direction `has*Page` values
10
- attr_accessor :bidirectional_pagination
17
+ def bidirectional_pagination=(new_setting)
18
+ if new_setting
19
+ warn("GraphQL::Relay::ConnectionType will be removed in GraphQL 2.0.0; migrate to `GraphQL::Pagination::Connections` and remove this setting (`bidirectional_pagination = true`).")
20
+ end
21
+ @bidirectional_pagination = new_setting
22
+ end
23
+ attr_reader :bidirectional_pagination
11
24
  end
12
25
 
13
26
  self.default_nodes_field = false
@@ -20,7 +33,7 @@ module GraphQL
20
33
  # Any call that would trigger `wrapped_type.ensure_defined`
21
34
  # must be inside this lazy block, otherwise we get weird
22
35
  # cyclical dependency errors :S
23
- ObjectType.define do
36
+ ObjectType.deprecated_define do
24
37
  type_name = wrapped_type.is_a?(GraphQL::BaseType) ? wrapped_type.name : wrapped_type.graphql_name
25
38
  edge_type ||= wrapped_type.edge_type
26
39
  name("#{type_name}Connection")
@@ -16,7 +16,6 @@ module GraphQL
16
16
  end
17
17
  end
18
18
 
19
-
20
19
  class EdgesResolve
21
20
  def initialize(edge_class:, resolve:)
22
21
  @edge_class = edge_class
@@ -10,8 +10,7 @@ module GraphQL
10
10
  if obj.is_a?(GraphQL::Schema::Object)
11
11
  obj = obj.object
12
12
  end
13
- type = @type.respond_to?(:graphql_definition) ? @type.graphql_definition : @type
14
- ctx.query.schema.id_from_object(obj, type, ctx)
13
+ ctx.query.schema.id_from_object(obj, @type, ctx)
15
14
  end
16
15
  end
17
16
  end
@@ -8,7 +8,7 @@ module GraphQL
8
8
  # @api deprecated
9
9
  class Mutation
10
10
  include GraphQL::Define::InstanceDefinable
11
- accepts_definitions(
11
+ deprecated_accepts_definitions(
12
12
  :name, :description, :resolve,
13
13
  :return_type,
14
14
  :return_interfaces,
@@ -30,6 +30,7 @@ module GraphQL
30
30
  alias :input_fields :arguments
31
31
 
32
32
  def initialize
33
+ GraphQL::Deprecation.warn "GraphQL::Relay::Mutation will be removed from GraphQL-Ruby 2.0, use GraphQL::Schema::RelayClassicMutation instead: https://graphql-ruby.org/mutations/mutation_classes"
33
34
  @fields = {}
34
35
  @arguments = {}
35
36
  @has_generated_return_type = false
@@ -5,6 +5,7 @@ module GraphQL
5
5
  module Node
6
6
  # @return [GraphQL::Field] a field for finding objects by their global ID.
7
7
  def self.field(**kwargs, &block)
8
+ GraphQL::Deprecation.warn "GraphQL::Relay::Node.field will be removed from GraphQL-Ruby 2.0, use GraphQL::Types::Relay::NodeField instead"
8
9
  # We have to define it fresh each time because
9
10
  # its name will be modified and its description
10
11
  # _may_ be modified.
@@ -18,6 +19,7 @@ module GraphQL
18
19
  end
19
20
 
20
21
  def self.plural_field(**kwargs, &block)
22
+ GraphQL::Deprecation.warn "GraphQL::Relay::Nodes.field will be removed from GraphQL-Ruby 2.0, use GraphQL::Types::Relay::NodesField instead"
21
23
  field = GraphQL::Types::Relay::NodesField.graphql_definition
22
24
 
23
25
  if kwargs.any? || block
@@ -29,6 +31,7 @@ module GraphQL
29
31
 
30
32
  # @return [GraphQL::InterfaceType] The interface which all Relay types must implement
31
33
  def self.interface
34
+ GraphQL::Deprecation.warn "GraphQL::Relay::Node.interface will be removed from GraphQL-Ruby 2.0, use GraphQL::Types::Relay::Node instead"
32
35
  @interface ||= GraphQL::Types::Relay::Node.graphql_definition
33
36
  end
34
37
  end
@@ -2,6 +2,6 @@
2
2
  module GraphQL
3
3
  module Relay
4
4
  # Wrap a Connection and expose its page info
5
- PageInfo = GraphQL::Types::Relay::PageInfo.graphql_definition
5
+ PageInfo = GraphQL::Types::Relay::PageInfo.graphql_definition(silence_deprecation_warning: true)
6
6
  end
7
7
  end
@@ -9,7 +9,7 @@ module GraphQL
9
9
  # should be ordered and paginated before providing it here.
10
10
  #
11
11
  # @example Adding a comment to list of comments
12
- # post = Post.find(args[:postId])
12
+ # post = Post.find(args[:post_id])
13
13
  # comments = post.comments
14
14
  # new_comment = comments.build(body: args[:body])
15
15
  # new_comment.save!
@@ -18,13 +18,13 @@ module GraphQL
18
18
  # parent: post,
19
19
  # collection: comments,
20
20
  # item: new_comment,
21
- # context: ctx,
21
+ # context: context,
22
22
  # )
23
23
  #
24
24
  # response = {
25
25
  # post: post,
26
- # commentsConnection: range_add.connection,
27
- # newCommentEdge: range_add.edge,
26
+ # comments_connection: range_add.connection,
27
+ # new_comment_edge: range_add.edge,
28
28
  # }
29
29
  class RangeAdd
30
30
  attr_reader :edge, :connection, :parent
@@ -35,11 +35,20 @@ module GraphQL
35
35
  # @param context [GraphQL::Query::Context] The surrounding `ctx`, will be passed to the connection if provided (this is required for cursor encoders)
36
36
  # @param edge_class [Class] The class to wrap `item` with (defaults to the connection's edge class)
37
37
  def initialize(collection:, item:, parent: nil, context: nil, edge_class: nil)
38
+ if context.nil?
39
+ caller_loc = caller(2, 1).first
40
+ GraphQL::Deprecation.warn("`context: ...` will be required by `RangeAdd.new` in GraphQL-Ruby 2.0. Add `context: context` to the call at #{caller_loc}.")
41
+ end
38
42
  if context && context.schema.new_connections?
39
43
  conn_class = context.schema.connections.wrapper_for(collection)
40
44
  # The rest will be added by ConnectionExtension
41
45
  @connection = conn_class.new(collection, parent: parent, context: context, edge_class: edge_class)
42
- @edge = @connection.edge_class.new(item, @connection)
46
+ # Check if this connection supports it, to support old versions of GraphQL-Pro
47
+ @edge = if @connection.respond_to?(:range_add_edge)
48
+ @connection.range_add_edge(item)
49
+ else
50
+ @connection.edge_class.new(item, @connection)
51
+ end
43
52
  else
44
53
  connection_class = BaseConnection.connection_for_nodes(collection)
45
54
  @connection = connection_class.new(collection, {}, parent: parent, context: context)
@@ -12,6 +12,7 @@ module GraphQL
12
12
  # Define a custom connection type for this object type
13
13
  # @return [GraphQL::ObjectType]
14
14
  def define_connection(**kwargs, &block)
15
+ GraphQL::Deprecation.warn ".connection_type and .define_connection will be removed from GraphQL-Ruby 2.0, use class-based type definitions instead: https://graphql-ruby.org/schema/class_based_api.html"
15
16
  GraphQL::Relay::ConnectionType.create_type(self, **kwargs, &block)
16
17
  end
17
18
 
@@ -23,6 +24,7 @@ module GraphQL
23
24
  # Define a custom edge type for this object type
24
25
  # @return [GraphQL::ObjectType]
25
26
  def define_edge(**kwargs, &block)
27
+ GraphQL::Deprecation.warn ".edge_type and .define_edge will be removed from GraphQL-Ruby 2.0, use class-based type definitions instead: https://graphql-ruby.org/schema/class_based_api.html"
26
28
  GraphQL::Relay::EdgeType.create_type(self, **kwargs, &block)
27
29
  end
28
30
  end