graphql 1.13.14 → 2.0.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 (261) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install_generator.rb +1 -1
  3. data/lib/generators/graphql/relay.rb +3 -17
  4. data/lib/generators/graphql/templates/schema.erb +3 -0
  5. data/lib/graphql/analysis/ast/field_usage.rb +3 -1
  6. data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
  7. data/lib/graphql/analysis/ast/query_complexity.rb +1 -1
  8. data/lib/graphql/analysis/ast/query_depth.rb +0 -1
  9. data/lib/graphql/analysis/ast/visitor.rb +43 -36
  10. data/lib/graphql/analysis/ast.rb +2 -12
  11. data/lib/graphql/analysis.rb +0 -7
  12. data/lib/graphql/backtrace/table.rb +2 -20
  13. data/lib/graphql/backtrace/tracer.rb +2 -3
  14. data/lib/graphql/backtrace.rb +2 -8
  15. data/lib/graphql/dataloader/null_dataloader.rb +3 -1
  16. data/lib/graphql/dataloader/source.rb +9 -0
  17. data/lib/graphql/dataloader.rb +4 -1
  18. data/lib/graphql/dig.rb +1 -1
  19. data/lib/graphql/execution/errors.rb +12 -82
  20. data/lib/graphql/execution/interpreter/resolve.rb +26 -0
  21. data/lib/graphql/execution/interpreter/runtime.rb +163 -120
  22. data/lib/graphql/execution/interpreter.rb +187 -78
  23. data/lib/graphql/execution/lazy.rb +7 -21
  24. data/lib/graphql/execution/lookahead.rb +44 -40
  25. data/lib/graphql/execution/multiplex.rb +3 -174
  26. data/lib/graphql/execution.rb +11 -4
  27. data/lib/graphql/introspection/directive_type.rb +2 -2
  28. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  29. data/lib/graphql/introspection/entry_points.rb +2 -15
  30. data/lib/graphql/introspection/field_type.rb +1 -1
  31. data/lib/graphql/introspection/schema_type.rb +2 -2
  32. data/lib/graphql/introspection/type_type.rb +13 -6
  33. data/lib/graphql/introspection.rb +4 -3
  34. data/lib/graphql/language/document_from_schema_definition.rb +18 -35
  35. data/lib/graphql/language/lexer.rb +216 -1488
  36. data/lib/graphql/language/lexer.ri +744 -0
  37. data/lib/graphql/language/nodes.rb +41 -33
  38. data/lib/graphql/language/parser.rb +375 -363
  39. data/lib/graphql/language/parser.y +48 -43
  40. data/lib/graphql/language/printer.rb +37 -21
  41. data/lib/graphql/language/visitor.rb +191 -83
  42. data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
  43. data/lib/graphql/pagination/array_connection.rb +4 -2
  44. data/lib/graphql/pagination/connection.rb +31 -4
  45. data/lib/graphql/pagination/connections.rb +3 -28
  46. data/lib/graphql/pagination/relation_connection.rb +2 -0
  47. data/lib/graphql/query/context.rb +155 -196
  48. data/lib/graphql/query/input_validation_result.rb +10 -1
  49. data/lib/graphql/query/null_context.rb +0 -3
  50. data/lib/graphql/query/validation_pipeline.rb +12 -37
  51. data/lib/graphql/query/variable_validation_error.rb +2 -2
  52. data/lib/graphql/query/variables.rb +35 -21
  53. data/lib/graphql/query.rb +32 -43
  54. data/lib/graphql/railtie.rb +0 -104
  55. data/lib/graphql/rake_task/validate.rb +1 -1
  56. data/lib/graphql/rake_task.rb +29 -1
  57. data/lib/graphql/relay/range_add.rb +9 -20
  58. data/lib/graphql/relay.rb +0 -15
  59. data/lib/graphql/schema/addition.rb +7 -9
  60. data/lib/graphql/schema/argument.rb +36 -43
  61. data/lib/graphql/schema/build_from_definition.rb +32 -18
  62. data/lib/graphql/schema/directive/one_of.rb +12 -0
  63. data/lib/graphql/schema/directive/transform.rb +1 -1
  64. data/lib/graphql/schema/directive.rb +12 -23
  65. data/lib/graphql/schema/enum.rb +29 -41
  66. data/lib/graphql/schema/enum_value.rb +5 -25
  67. data/lib/graphql/schema/field/connection_extension.rb +4 -0
  68. data/lib/graphql/schema/field.rb +245 -343
  69. data/lib/graphql/schema/input_object.rb +57 -69
  70. data/lib/graphql/schema/interface.rb +0 -35
  71. data/lib/graphql/schema/introspection_system.rb +3 -8
  72. data/lib/graphql/schema/late_bound_type.rb +8 -2
  73. data/lib/graphql/schema/list.rb +18 -9
  74. data/lib/graphql/schema/loader.rb +1 -2
  75. data/lib/graphql/schema/member/base_dsl_methods.rb +15 -19
  76. data/lib/graphql/schema/member/build_type.rb +5 -7
  77. data/lib/graphql/schema/member/has_arguments.rb +146 -55
  78. data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
  79. data/lib/graphql/schema/member/has_directives.rb +71 -56
  80. data/lib/graphql/schema/member/has_fields.rb +16 -4
  81. data/lib/graphql/schema/member/has_interfaces.rb +49 -10
  82. data/lib/graphql/schema/member/has_validators.rb +31 -5
  83. data/lib/graphql/schema/member/relay_shortcuts.rb +28 -2
  84. data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
  85. data/lib/graphql/schema/member/validates_input.rb +3 -3
  86. data/lib/graphql/schema/member.rb +0 -6
  87. data/lib/graphql/schema/mutation.rb +0 -9
  88. data/lib/graphql/schema/non_null.rb +3 -9
  89. data/lib/graphql/schema/object.rb +15 -52
  90. data/lib/graphql/schema/relay_classic_mutation.rb +53 -42
  91. data/lib/graphql/schema/resolver/has_payload_type.rb +20 -10
  92. data/lib/graphql/schema/resolver.rb +41 -42
  93. data/lib/graphql/schema/scalar.rb +8 -23
  94. data/lib/graphql/schema/subscription.rb +0 -7
  95. data/lib/graphql/schema/timeout.rb +24 -28
  96. data/lib/graphql/schema/type_membership.rb +3 -0
  97. data/lib/graphql/schema/union.rb +10 -17
  98. data/lib/graphql/schema/warden.rb +34 -8
  99. data/lib/graphql/schema/wrapper.rb +0 -5
  100. data/lib/graphql/schema.rb +240 -968
  101. data/lib/graphql/static_validation/all_rules.rb +1 -0
  102. data/lib/graphql/static_validation/base_visitor.rb +4 -21
  103. data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
  104. data/lib/graphql/static_validation/error.rb +2 -2
  105. data/lib/graphql/static_validation/literal_validator.rb +19 -1
  106. data/lib/graphql/static_validation/rules/directives_are_defined.rb +11 -5
  107. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +12 -12
  108. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  109. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  110. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +12 -6
  111. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -1
  112. data/lib/graphql/static_validation/validator.rb +3 -25
  113. data/lib/graphql/static_validation.rb +0 -2
  114. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -1
  115. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +38 -1
  116. data/lib/graphql/subscriptions/event.rb +3 -8
  117. data/lib/graphql/subscriptions/instrumentation.rb +0 -51
  118. data/lib/graphql/subscriptions.rb +32 -20
  119. data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
  120. data/lib/graphql/tracing/appoptics_trace.rb +231 -0
  121. data/lib/graphql/tracing/appsignal_trace.rb +66 -0
  122. data/lib/graphql/tracing/data_dog_trace.rb +148 -0
  123. data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
  124. data/lib/graphql/tracing/new_relic_trace.rb +75 -0
  125. data/lib/graphql/tracing/notifications_trace.rb +41 -0
  126. data/lib/graphql/tracing/platform_trace.rb +107 -0
  127. data/lib/graphql/tracing/platform_tracing.rb +26 -40
  128. data/lib/graphql/tracing/prometheus_trace.rb +89 -0
  129. data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
  130. data/lib/graphql/tracing/scout_trace.rb +72 -0
  131. data/lib/graphql/tracing/statsd_trace.rb +56 -0
  132. data/lib/graphql/tracing.rb +136 -41
  133. data/lib/graphql/type_kinds.rb +6 -3
  134. data/lib/graphql/types/iso_8601_date.rb +4 -1
  135. data/lib/graphql/types/iso_8601_date_time.rb +4 -0
  136. data/lib/graphql/types/relay/base_connection.rb +16 -6
  137. data/lib/graphql/types/relay/connection_behaviors.rb +5 -25
  138. data/lib/graphql/types/relay/default_relay.rb +5 -9
  139. data/lib/graphql/types/relay/edge_behaviors.rb +1 -4
  140. data/lib/graphql/types/relay/node_behaviors.rb +5 -1
  141. data/lib/graphql/types/relay.rb +0 -2
  142. data/lib/graphql/types/string.rb +1 -1
  143. data/lib/graphql/version.rb +1 -1
  144. data/lib/graphql.rb +11 -72
  145. metadata +31 -133
  146. data/lib/graphql/analysis/analyze_query.rb +0 -98
  147. data/lib/graphql/analysis/field_usage.rb +0 -45
  148. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  149. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  150. data/lib/graphql/analysis/query_complexity.rb +0 -88
  151. data/lib/graphql/analysis/query_depth.rb +0 -43
  152. data/lib/graphql/analysis/reducer_state.rb +0 -48
  153. data/lib/graphql/argument.rb +0 -131
  154. data/lib/graphql/authorization.rb +0 -82
  155. data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
  156. data/lib/graphql/backwards_compatibility.rb +0 -61
  157. data/lib/graphql/base_type.rb +0 -232
  158. data/lib/graphql/boolean_type.rb +0 -2
  159. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  160. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  161. data/lib/graphql/compatibility/execution_specification.rb +0 -436
  162. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  163. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
  164. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
  165. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  166. data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
  167. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
  168. data/lib/graphql/compatibility.rb +0 -5
  169. data/lib/graphql/define/assign_argument.rb +0 -12
  170. data/lib/graphql/define/assign_connection.rb +0 -13
  171. data/lib/graphql/define/assign_enum_value.rb +0 -18
  172. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  173. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  174. data/lib/graphql/define/assign_object_field.rb +0 -42
  175. data/lib/graphql/define/defined_object_proxy.rb +0 -53
  176. data/lib/graphql/define/instance_definable.rb +0 -255
  177. data/lib/graphql/define/no_definition_error.rb +0 -7
  178. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  179. data/lib/graphql/define/type_definer.rb +0 -31
  180. data/lib/graphql/define.rb +0 -31
  181. data/lib/graphql/deprecated_dsl.rb +0 -55
  182. data/lib/graphql/directive/deprecated_directive.rb +0 -2
  183. data/lib/graphql/directive/include_directive.rb +0 -2
  184. data/lib/graphql/directive/skip_directive.rb +0 -2
  185. data/lib/graphql/directive.rb +0 -107
  186. data/lib/graphql/enum_type.rb +0 -133
  187. data/lib/graphql/execution/execute.rb +0 -333
  188. data/lib/graphql/execution/flatten.rb +0 -40
  189. data/lib/graphql/execution/instrumentation.rb +0 -92
  190. data/lib/graphql/execution/lazy/resolve.rb +0 -91
  191. data/lib/graphql/execution/typecast.rb +0 -50
  192. data/lib/graphql/field/resolve.rb +0 -59
  193. data/lib/graphql/field.rb +0 -226
  194. data/lib/graphql/float_type.rb +0 -2
  195. data/lib/graphql/function.rb +0 -128
  196. data/lib/graphql/id_type.rb +0 -2
  197. data/lib/graphql/input_object_type.rb +0 -138
  198. data/lib/graphql/int_type.rb +0 -2
  199. data/lib/graphql/interface_type.rb +0 -72
  200. data/lib/graphql/internal_representation/document.rb +0 -27
  201. data/lib/graphql/internal_representation/node.rb +0 -206
  202. data/lib/graphql/internal_representation/print.rb +0 -51
  203. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  204. data/lib/graphql/internal_representation/scope.rb +0 -88
  205. data/lib/graphql/internal_representation/visit.rb +0 -36
  206. data/lib/graphql/internal_representation.rb +0 -7
  207. data/lib/graphql/language/lexer.rl +0 -260
  208. data/lib/graphql/list_type.rb +0 -80
  209. data/lib/graphql/non_null_type.rb +0 -71
  210. data/lib/graphql/object_type.rb +0 -130
  211. data/lib/graphql/query/arguments.rb +0 -189
  212. data/lib/graphql/query/arguments_cache.rb +0 -24
  213. data/lib/graphql/query/executor.rb +0 -52
  214. data/lib/graphql/query/literal_input.rb +0 -136
  215. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  216. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  217. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  218. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  219. data/lib/graphql/query/serial_execution.rb +0 -40
  220. data/lib/graphql/relay/array_connection.rb +0 -83
  221. data/lib/graphql/relay/base_connection.rb +0 -189
  222. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  223. data/lib/graphql/relay/connection_resolve.rb +0 -43
  224. data/lib/graphql/relay/connection_type.rb +0 -54
  225. data/lib/graphql/relay/edge.rb +0 -27
  226. data/lib/graphql/relay/edge_type.rb +0 -19
  227. data/lib/graphql/relay/edges_instrumentation.rb +0 -39
  228. data/lib/graphql/relay/global_id_resolve.rb +0 -17
  229. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  230. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  231. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  232. data/lib/graphql/relay/mutation/result.rb +0 -38
  233. data/lib/graphql/relay/mutation.rb +0 -106
  234. data/lib/graphql/relay/node.rb +0 -39
  235. data/lib/graphql/relay/page_info.rb +0 -7
  236. data/lib/graphql/relay/relation_connection.rb +0 -188
  237. data/lib/graphql/relay/type_extensions.rb +0 -32
  238. data/lib/graphql/scalar_type.rb +0 -91
  239. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  240. data/lib/graphql/schema/default_parse_error.rb +0 -10
  241. data/lib/graphql/schema/default_type_error.rb +0 -17
  242. data/lib/graphql/schema/member/accepts_definition.rb +0 -164
  243. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -58
  244. data/lib/graphql/schema/member/instrumentation.rb +0 -131
  245. data/lib/graphql/schema/middleware_chain.rb +0 -82
  246. data/lib/graphql/schema/possible_types.rb +0 -44
  247. data/lib/graphql/schema/rescue_middleware.rb +0 -60
  248. data/lib/graphql/schema/timeout_middleware.rb +0 -88
  249. data/lib/graphql/schema/traversal.rb +0 -228
  250. data/lib/graphql/schema/validation.rb +0 -313
  251. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  252. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  253. data/lib/graphql/string_type.rb +0 -2
  254. data/lib/graphql/subscriptions/subscription_root.rb +0 -76
  255. data/lib/graphql/tracing/opentelemetry_tracing.rb +0 -101
  256. data/lib/graphql/tracing/skylight_tracing.rb +0 -70
  257. data/lib/graphql/types/relay/node_field.rb +0 -24
  258. data/lib/graphql/types/relay/nodes_field.rb +0 -43
  259. data/lib/graphql/union_type.rb +0 -115
  260. data/lib/graphql/upgrader/member.rb +0 -937
  261. data/lib/graphql/upgrader/schema.rb +0 -38
@@ -16,10 +16,8 @@ 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
- @internal_representation = nil
22
- @validate = validate
23
21
  @parse_error = parse_error
24
22
  @operation_name_error = operation_name_error
25
23
  @query = query
@@ -42,17 +40,15 @@ module GraphQL
42
40
  @validation_errors
43
41
  end
44
42
 
45
- # @return [Hash<String, nil => GraphQL::InternalRepresentation::Node] Operation name -> Irep node pairs
46
- def internal_representation
47
- ensure_has_validated
48
- @internal_representation
49
- end
50
-
51
43
  def analyzers
52
44
  ensure_has_validated
53
45
  @query_analyzers
54
46
  end
55
47
 
48
+ def has_validated?
49
+ @has_validated == true
50
+ end
51
+
56
52
  private
57
53
 
58
54
  # If the pipeline wasn't run yet, run it.
@@ -63,7 +59,7 @@ module GraphQL
63
59
 
64
60
  if @parse_error
65
61
  # This is kind of crazy: we push the parse error into `ctx`
66
- # in {DefaultParseError} so that users can _opt out_ by redefining that hook.
62
+ # in `def self.parse_error` by default so that users can _opt out_ by redefining that hook.
67
63
  # That means we can't _re-add_ the error here (otherwise we'd either
68
64
  # add it twice _or_ override the user's choice to not add it).
69
65
  # So we just have to know that it was invalid and go from there.
@@ -72,9 +68,8 @@ module GraphQL
72
68
  elsif @operation_name_error
73
69
  @validation_errors << @operation_name_error
74
70
  else
75
- validation_result = @schema.static_validator.validate(@query, validate: @validate, timeout: @schema.validate_timeout, max_errors: @schema.validate_max_errors)
71
+ validation_result = @schema.static_validator.validate(@query, validate: @query.validate, timeout: @schema.validate_timeout, max_errors: @schema.validate_max_errors)
76
72
  @validation_errors.concat(validation_result[:errors])
77
- @internal_representation = validation_result[:irep]
78
73
 
79
74
  if @validation_errors.empty?
80
75
  @validation_errors.concat(@query.variables.errors)
@@ -100,35 +95,15 @@ module GraphQL
100
95
  def build_analyzers(schema, max_depth, max_complexity)
101
96
  qa = schema.query_analyzers.dup
102
97
 
103
- # Filter out the built in authorization analyzer.
104
- # It is deprecated and does not have an AST analyzer alternative.
105
- qa = qa.select do |analyzer|
106
- if analyzer == GraphQL::Authorization::Analyzer && schema.using_ast_analysis?
107
- raise "The Authorization analyzer is not supported with AST Analyzers"
108
- else
109
- true
110
- end
111
- end
112
-
113
98
  if max_depth || max_complexity
114
99
  # Depending on the analysis engine, we must use different analyzers
115
100
  # remove this once everything has switched over to AST analyzers
116
- if schema.using_ast_analysis?
117
- if max_depth
118
- qa << GraphQL::Analysis::AST::MaxQueryDepth
119
- end
120
- if max_complexity
121
- qa << GraphQL::Analysis::AST::MaxQueryComplexity
122
- end
123
- else
124
- if max_depth
125
- qa << GraphQL::Analysis::MaxQueryDepth.new(max_depth)
126
- end
127
- if max_complexity
128
- qa << GraphQL::Analysis::MaxQueryComplexity.new(max_complexity)
129
- end
101
+ if max_depth
102
+ qa << GraphQL::Analysis::AST::MaxQueryDepth
103
+ end
104
+ if max_complexity
105
+ qa << GraphQL::Analysis::AST::MaxQueryComplexity
130
106
  end
131
-
132
107
  qa
133
108
  else
134
109
  qa
@@ -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(", ")}"
@@ -14,9 +14,13 @@ module GraphQL
14
14
  schema = ctx.schema
15
15
  @context = ctx
16
16
 
17
- @provided_variables = GraphQL::Argument.deep_stringify(provided_variables)
17
+ @provided_variables = 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,30 +33,18 @@ 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
37
- memo[variable_name] = if ctx.interpreter?
38
- provided_value
39
- elsif provided_value.nil?
40
- nil
41
- else
42
- schema.error_handler.with_error_handling(context) do
43
- variable_type.coerce_input(provided_value, ctx)
44
- end
45
- end
42
+ memo[variable_name] = provided_value
46
43
  elsif default_value != nil
47
- memo[variable_name] = if ctx.interpreter?
48
- if default_value.is_a?(Language::Nodes::NullValue)
49
- nil
50
- else
51
- default_value
52
- end
44
+ memo[variable_name] = if default_value.is_a?(Language::Nodes::NullValue)
45
+ nil
53
46
  else
54
- # Add the variable if it wasn't provided but it has a default value (including `null`)
55
- GraphQL::Query::LiteralInput.coerce(variable_type, default_value, self)
47
+ default_value
56
48
  end
57
49
  end
58
50
  end
@@ -61,8 +53,7 @@ module GraphQL
61
53
  # like InputValidationResults generated by validate_non_null_input but unfortunately we don't
62
54
  # have this information available in the coerce_input call chain. Note this path is the path
63
55
  # that appears under errors.extensions.problems.path and NOT the result path under errors.path.
64
- validation_result = GraphQL::Query::InputValidationResult.new
65
- validation_result.add_problem(ex.message)
56
+ validation_result = GraphQL::Query::InputValidationResult.from_problem(ex.message)
66
57
  end
67
58
 
68
59
  if !validation_result.valid?
@@ -73,6 +64,29 @@ module GraphQL
73
64
  end
74
65
 
75
66
  def_delegators :@storage, :length, :key?, :[], :fetch, :to_h
67
+
68
+ private
69
+
70
+ def deep_stringify(val)
71
+ case val
72
+ when Array
73
+ val.map { |v| deep_stringify(v) }
74
+ when Hash
75
+ new_val = {}
76
+ val.each do |k, v|
77
+ new_val[k.to_s] = deep_stringify(v)
78
+ end
79
+ new_val
80
+ else
81
+ val
82
+ end
83
+ end
84
+
85
+ def add_max_errors_reached_message
86
+ message = "Too many errors processing variables, max validation error limit reached. Execution aborted"
87
+ validation_result = GraphQL::Query::InputValidationResult.from_problem(message)
88
+ errors << GraphQL::Query::VariableValidationError.new(nil, nil, nil, validation_result, msg: message)
89
+ end
76
90
  end
77
91
  end
78
92
  end
data/lib/graphql/query.rb CHANGED
@@ -1,13 +1,8 @@
1
1
  # frozen_string_literal: true
2
- require "graphql/query/arguments"
3
- require "graphql/query/arguments_cache"
4
2
  require "graphql/query/context"
5
- require "graphql/query/executor"
6
3
  require "graphql/query/fingerprint"
7
- require "graphql/query/literal_input"
8
4
  require "graphql/query/null_context"
9
5
  require "graphql/query/result"
10
- require "graphql/query/serial_execution"
11
6
  require "graphql/query/variables"
12
7
  require "graphql/query/input_validation_result"
13
8
  require "graphql/query/variable_validation_error"
@@ -39,7 +34,16 @@ module GraphQL
39
34
  attr_accessor :operation_name
40
35
 
41
36
  # @return [Boolean] if false, static validation is skipped (execution behavior for invalid queries is undefined)
42
- attr_accessor :validate
37
+ attr_reader :validate
38
+
39
+ # @param new_validate [Boolean] if false, static validation is skipped. This can't be reasssigned after validation.
40
+ def validate=(new_validate)
41
+ if defined?(@validation_pipeline) && @validation_pipeline && @validation_pipeline.has_validated?
42
+ raise ArgumentError, "Can't reassign Query#validate= after validation has run, remove this assignment."
43
+ else
44
+ @validate = new_validate
45
+ end
46
+ end
43
47
 
44
48
  attr_writer :query_string
45
49
 
@@ -82,13 +86,7 @@ module GraphQL
82
86
  def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, except: nil, only: nil, warden: nil)
83
87
  # Even if `variables: nil` is passed, use an empty hash for simpler logic
84
88
  variables ||= {}
85
-
86
- # Use the `.graphql_definition` here which will return legacy types instead of classes
87
- if schema.is_a?(Class) && !schema.interpreter?
88
- schema = schema.graphql_definition
89
- end
90
89
  @schema = schema
91
- @interpreter = @schema.interpreter?
92
90
  @filter = schema.default_filter.merge(except: except, only: only)
93
91
  @context = schema.context_class.new(query: self, object: root_value, values: context)
94
92
  @warden = warden
@@ -97,12 +95,20 @@ module GraphQL
97
95
  @fragments = nil
98
96
  @operations = nil
99
97
  @validate = validate
100
- @tracers = schema.tracers + (context ? context.fetch(:tracers, []) : [])
98
+ context_tracers = (context ? context.fetch(:tracers, []) : [])
99
+ @tracers = schema.tracers + context_tracers
100
+
101
101
  # Support `ctx[:backtrace] = true` for wrapping backtraces
102
102
  if context && context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
103
+ context_tracers += [GraphQL::Backtrace::Tracer]
103
104
  @tracers << GraphQL::Backtrace::Tracer
104
105
  end
105
106
 
107
+ if context_tracers.any? && !(schema.trace_class <= GraphQL::Tracing::LegacyTrace)
108
+ raise ArgumentError, "context[:tracers] and context[:backtrace] are not supported without `tracer_class(GraphQL::Tracing::LegacyTrace)` in the schema configuration, please add it."
109
+ end
110
+
111
+
106
112
  @analysis_errors = []
107
113
  if variables.is_a?(String)
108
114
  raise ArgumentError, "Query variables should be a Hash, not a String. Try JSON.parse to prepare variables."
@@ -154,11 +160,16 @@ module GraphQL
154
160
  end
155
161
 
156
162
  def interpreter?
157
- @interpreter
163
+ true
158
164
  end
159
165
 
160
166
  attr_accessor :multiplex
161
167
 
168
+ # @return [GraphQL::Tracing::Trace]
169
+ def current_trace
170
+ @current_trace ||= multiplex ? multiplex.current_trace : schema.new_trace(multiplex: multiplex, query: self)
171
+ end
172
+
162
173
  def subscription_update?
163
174
  @subscription_topic && subscription?
164
175
  end
@@ -169,7 +180,6 @@ module GraphQL
169
180
  @lookahead ||= begin
170
181
  ast_node = selected_operation
171
182
  root_type = warden.root_type_for_operation(ast_node.operation_type || "query")
172
- root_type = root_type.type_class || raise("Invariant: `lookahead` only works with class-based types")
173
183
  GraphQL::Execution::Lookahead.new(query: self, root_type: root_type, ast_nodes: [ast_node])
174
184
  end
175
185
  end
@@ -199,7 +209,7 @@ module GraphQL
199
209
  # @return [Hash] A GraphQL response, with `"data"` and/or `"errors"` keys
200
210
  def result
201
211
  if !@executed
202
- Execution::Multiplex.run_queries(@schema, [self], context: @context)
212
+ Execution::Interpreter.run_all(@schema, [self], context: @context)
203
213
  end
204
214
  @result ||= Query::Result.new(query: self, values: @result_values)
205
215
  end
@@ -237,35 +247,17 @@ module GraphQL
237
247
  end
238
248
  end
239
249
 
240
- def irep_selection
241
- @selection ||= begin
242
- if selected_operation && internal_representation
243
- internal_representation.operation_definitions[selected_operation.name]
244
- else
245
- nil
246
- end
247
- end
248
- end
249
-
250
250
  # Node-level cache for calculating arguments. Used during execution and query analysis.
251
251
  # @param ast_node [GraphQL::Language::Nodes::AbstractNode]
252
252
  # @param definition [GraphQL::Schema::Field]
253
253
  # @param parent_object [GraphQL::Schema::Object]
254
254
  # @return Hash{Symbol => Object}
255
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
256
+ arguments_cache.fetch(ast_node, definition, parent_object)
261
257
  end
262
258
 
263
259
  def arguments_cache
264
- if interpreter?
265
- @arguments_cache ||= Execution::Interpreter::ArgumentsCache.new(self)
266
- else
267
- @arguments_cache ||= ArgumentsCache.build(self)
268
- end
260
+ @arguments_cache ||= Execution::Interpreter::ArgumentsCache.new(self)
269
261
  end
270
262
 
271
263
  # A version of the given query string, with:
@@ -308,7 +300,7 @@ module GraphQL
308
300
  with_prepared_ast { @validation_pipeline }
309
301
  end
310
302
 
311
- def_delegators :validation_pipeline, :validation_errors, :internal_representation,
303
+ def_delegators :validation_pipeline, :validation_errors,
312
304
  :analyzers, :ast_analyzers, :max_depth, :max_complexity
313
305
 
314
306
  attr_accessor :analysis_errors
@@ -361,10 +353,8 @@ module GraphQL
361
353
  end
362
354
 
363
355
  # @api private
364
- def with_error_handling
365
- schema.error_handler.with_error_handling(context) do
366
- yield
367
- end
356
+ def handle_or_reraise(err)
357
+ schema.handle_or_reraise(context, err)
368
358
  end
369
359
 
370
360
  private
@@ -385,7 +375,7 @@ module GraphQL
385
375
  parse_error = nil
386
376
  @document ||= begin
387
377
  if query_string
388
- GraphQL.parse(query_string, tracer: self)
378
+ GraphQL.parse(query_string, trace: self.current_trace)
389
379
  end
390
380
  rescue GraphQL::ParseError => err
391
381
  parse_error = err
@@ -434,7 +424,6 @@ module GraphQL
434
424
 
435
425
  @validation_pipeline = GraphQL::Query::ValidationPipeline.new(
436
426
  query: self,
437
- validate: @validate,
438
427
  parse_error: parse_error,
439
428
  operation_name_error: operation_name_error,
440
429
  max_depth: @max_depth,
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  module GraphQL
4
3
  class Railtie < Rails::Railtie
5
4
  config.before_configuration do
@@ -10,108 +9,5 @@ module GraphQL
10
9
  Language::Parser.cache ||= Language::Cache.new(Pathname.new(Bootsnap::CompileCache::ISeq.cache_dir).join('graphql'))
11
10
  end
12
11
  end
13
-
14
- rake_tasks do
15
- # Defer this so that you only need the `parser` gem when you _run_ the upgrader
16
- def load_upgraders
17
- require_relative './upgrader/member'
18
- require_relative './upgrader/schema'
19
- end
20
-
21
- namespace :graphql do
22
- task :upgrade, [:dir] do |t, args|
23
- unless (dir = args[:dir])
24
- fail 'You have to give me a directory where your GraphQL schema and types live. ' \
25
- 'For example: `bin/rake graphql:upgrade[app/graphql/**/*]`'
26
- end
27
-
28
- Dir[dir].each do |file|
29
- # Members (types, interfaces, etc.)
30
- if file =~ /.*_(type|interface|enum|union|)\.rb$/
31
- Rake::Task["graphql:upgrade:member"].execute(Struct.new(:member_file).new(file))
32
- end
33
- end
34
-
35
- puts "Upgrade complete! Note that this is a best-effort approach, and may very well contain some bugs."
36
- puts "Don't forget to create the base objects. For example, you could run:"
37
- puts "\tbin/rake graphql:upgrade:create_base_objects[app/graphql]"
38
- end
39
-
40
- namespace :upgrade do
41
- task :create_base_objects, [:base_dir] do |t, args|
42
- unless (base_dir = args[:base_dir])
43
- fail 'You have to give me a directory where your GraphQL types live. ' \
44
- 'For example: `bin/rake graphql:upgrade:create_base_objects[app/graphql]`'
45
- end
46
-
47
- destination_file = File.join(base_dir, "types", "base_scalar.rb")
48
- unless File.exists?(destination_file)
49
- FileUtils.mkdir_p(File.dirname(destination_file))
50
- File.open(destination_file, 'w') do |f|
51
- f.puts "class Types::BaseScalar < GraphQL::Schema::Scalar\nend"
52
- end
53
- end
54
-
55
- destination_file = File.join(base_dir, "types", "base_input_object.rb")
56
- unless File.exists?(destination_file)
57
- FileUtils.mkdir_p(File.dirname(destination_file))
58
- File.open(destination_file, 'w') do |f|
59
- f.puts "class Types::BaseInputObject < GraphQL::Schema::InputObject\nend"
60
- end
61
- end
62
-
63
- destination_file = File.join(base_dir, "types", "base_enum.rb")
64
- unless File.exists?(destination_file)
65
- FileUtils.mkdir_p(File.dirname(destination_file))
66
- File.open(destination_file, 'w') do |f|
67
- f.puts "class Types::BaseEnum < GraphQL::Schema::Enum\nend"
68
- end
69
- end
70
-
71
- destination_file = File.join(base_dir, "types", "base_union.rb")
72
- unless File.exists?(destination_file)
73
- FileUtils.mkdir_p(File.dirname(destination_file))
74
- File.open(destination_file, 'w') do |f|
75
- f.puts "class Types::BaseUnion < GraphQL::Schema::Union\nend"
76
- end
77
- end
78
-
79
- destination_file = File.join(base_dir, "types", "base_interface.rb")
80
- unless File.exists?(destination_file)
81
- FileUtils.mkdir_p(File.dirname(destination_file))
82
- File.open(destination_file, 'w') do |f|
83
- f.puts "module Types::BaseInterface\n include GraphQL::Schema::Interface\nend"
84
- end
85
- end
86
-
87
- destination_file = File.join(base_dir, "types", "base_object.rb")
88
- unless File.exists?(destination_file)
89
- File.open(destination_file, 'w') do |f|
90
- f.puts "class Types::BaseObject < GraphQL::Schema::Object\nend"
91
- end
92
- end
93
- end
94
-
95
- task :schema, [:schema_file] do |t, args|
96
- schema_file = args.schema_file
97
- load_upgraders
98
- upgrader = GraphQL::Upgrader::Schema.new File.read(schema_file)
99
-
100
- puts "- Transforming schema #{schema_file}"
101
- File.open(schema_file, 'w') { |f| f.write upgrader.upgrade }
102
- end
103
-
104
- task :member, [:member_file] do |t, args|
105
- member_file = args.member_file
106
- load_upgraders
107
- upgrader = GraphQL::Upgrader::Member.new File.read(member_file)
108
- next unless upgrader.upgradeable?
109
-
110
- puts "- Transforming member #{member_file}"
111
- File.open(member_file, 'w') { |f| f.write upgrader.upgrade }
112
- end
113
- end
114
- end
115
- end
116
12
  end
117
13
  end
@@ -15,7 +15,7 @@ module GraphQL
15
15
  puts "Validating graphql-pro v#{version}"
16
16
  puts " - Checking for graphql-pro credentials..."
17
17
 
18
- creds = `bundle config gems.graphql.pro`[/[a-z0-9]{11}:[a-z0-9]{11}/]
18
+ creds = `bundle config gems.graphql.pro --parseable`[/[a-z0-9]{11}:[a-z0-9]{11}/]
19
19
  if creds.nil?
20
20
  puts " #{ex} failed, please set with `bundle config gems.graphql.pro $MY_CREDENTIALS`"
21
21
  exit(1)
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require "fileutils"
3
+ require "rake"
3
4
  require "graphql/rake_task/validate"
4
5
 
5
6
  module GraphQL
@@ -22,6 +23,10 @@ module GraphQL
22
23
  # @example Invoking the task from Ruby
23
24
  # require "rake"
24
25
  # Rake::Task["graphql:schema:dump"].invoke
26
+ #
27
+ # @example Providing arguments to build the introspection query
28
+ # require "graphql/rake_task"
29
+ # GraphQL::RakeTask.new(schema_name: "MySchema", include_is_one_of: true)
25
30
  class RakeTask
26
31
  include Rake::DSL
27
32
 
@@ -36,6 +41,11 @@ module GraphQL
36
41
  directory: ".",
37
42
  idl_outfile: "schema.graphql",
38
43
  json_outfile: "schema.json",
44
+ include_deprecated_args: true,
45
+ include_schema_description: false,
46
+ include_is_repeatable: false,
47
+ include_specified_by_url: false,
48
+ include_is_one_of: false
39
49
  }
40
50
 
41
51
  # @return [String] Namespace for generated tasks
@@ -73,6 +83,10 @@ module GraphQL
73
83
  # @return [String] directory for IDL & JSON files
74
84
  attr_accessor :directory
75
85
 
86
+ # @return [Boolean] Options for additional fields in the introspection query JSON response
87
+ # @see GraphQL::Schema.as_json
88
+ attr_accessor :include_deprecated_args, :include_schema_description, :include_is_repeatable, :include_specified_by_url, :include_is_one_of
89
+
76
90
  # Set the parameters of this task by passing keyword arguments
77
91
  # or assigning attributes inside the block
78
92
  def initialize(options = {})
@@ -95,7 +109,21 @@ module GraphQL
95
109
  def write_outfile(method_name, file)
96
110
  schema = @load_schema.call(self)
97
111
  context = @load_context.call(self)
98
- result = schema.public_send(method_name, only: @only, except: @except, context: context)
112
+ result = case method_name
113
+ when :to_json
114
+ schema.to_json(
115
+ include_is_one_of: include_is_one_of,
116
+ include_deprecated_args: include_deprecated_args,
117
+ include_is_repeatable: include_is_repeatable,
118
+ include_specified_by_url: include_specified_by_url,
119
+ include_schema_description: include_schema_description,
120
+ only: @only, except: @except, context: context
121
+ )
122
+ when :to_definition
123
+ schema.to_definition(only: @only, except: @except, context: context)
124
+ else
125
+ raise ArgumentError, "Unexpected schema dump method: #{method_name.inspect}"
126
+ end
99
127
  dir = File.dirname(file)
100
128
  FileUtils.mkdir_p(dir)
101
129
  if !result.end_with?("\n")
@@ -31,29 +31,18 @@ module GraphQL
31
31
 
32
32
  # @param collection [Object] The list of items to wrap in a connection
33
33
  # @param item [Object] The newly-added item (will be wrapped in `edge_class`)
34
+ # @param context [GraphQL::Query::Context] The surrounding `ctx`, will be passed to the connection
34
35
  # @param parent [Object] The owner of `collection`, will be passed to the connection if provided
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
- 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
42
- if context && context.schema.new_connections?
43
- conn_class = context.schema.connections.wrapper_for(collection)
44
- # The rest will be added by ConnectionExtension
45
- @connection = conn_class.new(collection, parent: parent, context: context, edge_class: edge_class)
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
37
+ def initialize(collection:, item:, context:, parent: nil, edge_class: nil)
38
+ conn_class = context.schema.connections.wrapper_for(collection)
39
+ # The rest will be added by ConnectionExtension
40
+ @connection = conn_class.new(collection, parent: parent, context: context, edge_class: edge_class)
41
+ # Check if this connection supports it, to support old versions of GraphQL-Pro
42
+ @edge = if @connection.respond_to?(:range_add_edge)
43
+ @connection.range_add_edge(item)
52
44
  else
53
- connection_class = BaseConnection.connection_for_nodes(collection)
54
- @connection = connection_class.new(collection, {}, parent: parent, context: context)
55
- edge_class ||= Relay::Edge
56
- @edge = edge_class.new(item, @connection)
45
+ @connection.edge_class.new(item, @connection)
57
46
  end
58
47
 
59
48
  @parent = parent
data/lib/graphql/relay.rb CHANGED
@@ -1,18 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'graphql/relay/page_info'
4
- require 'graphql/relay/edge'
5
- require 'graphql/relay/edge_type'
6
- require 'graphql/relay/edges_instrumentation'
7
- require 'graphql/relay/base_connection'
8
- require 'graphql/relay/array_connection'
9
3
  require 'graphql/relay/range_add'
10
- require 'graphql/relay/relation_connection'
11
- require 'graphql/relay/mongo_relation_connection'
12
- require 'graphql/relay/global_id_resolve'
13
- require 'graphql/relay/mutation'
14
- require 'graphql/relay/node'
15
- require 'graphql/relay/connection_instrumentation'
16
- require 'graphql/relay/connection_resolve'
17
- require 'graphql/relay/connection_type'
18
- require 'graphql/relay/type_extensions'
@@ -107,6 +107,11 @@ module GraphQL
107
107
  if !pt.include?(owner) && owner.is_a?(Class)
108
108
  pt << owner
109
109
  end
110
+ int.interfaces.each do |indirect_int|
111
+ if indirect_int.is_a?(LateBoundType) && (indirect_int_type = get_type(indirect_int.graphql_name))
112
+ update_type_owner(owner, indirect_int_type)
113
+ end
114
+ end
110
115
  end
111
116
  end
112
117
  when nil
@@ -136,14 +141,7 @@ module GraphQL
136
141
  end
137
142
 
138
143
  def add_type(type, owner:, late_types:, path:)
139
- if type.respond_to?(:metadata) && type.metadata.is_a?(Hash)
140
- type_class = type.metadata[:type_class]
141
- if type_class.nil?
142
- raise ArgumentError, "Can't add legacy type: #{type} (#{type.class})"
143
- else
144
- type = type_class
145
- end
146
- elsif type.is_a?(String) || type.is_a?(GraphQL::Schema::LateBoundType)
144
+ if type.is_a?(String) || type.is_a?(GraphQL::Schema::LateBoundType)
147
145
  late_types << [owner, type]
148
146
  return
149
147
  end
@@ -153,7 +151,7 @@ module GraphQL
153
151
  um << owner
154
152
  end
155
153
 
156
- if (prev_type = get_local_type(type.graphql_name)) && prev_type == type
154
+ if (prev_type = get_local_type(type.graphql_name)) && (prev_type == type || (prev_type.is_a?(Array) && prev_type.include?(type)))
157
155
  # No need to re-visit
158
156
  elsif type.is_a?(Class) && type < GraphQL::Schema::Directive
159
157
  @directives << type