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
@@ -11,6 +11,7 @@ module GraphQL
11
11
  def self.extended(cls)
12
12
  cls.extend(ArgumentClassAccessor)
13
13
  cls.include(ArgumentObjectLoader)
14
+ cls.extend(ClassConfigured)
14
15
  end
15
16
 
16
17
  # @see {GraphQL::Schema::Argument#initialize} for parameters
@@ -37,39 +38,6 @@ module GraphQL
37
38
  end
38
39
  arg_defn = self.argument_class.new(*args, **kwargs, &block)
39
40
  add_argument(arg_defn)
40
-
41
- if self.is_a?(Class) && !method_defined?(:"load_#{arg_defn.keyword}")
42
- method_owner = if self < GraphQL::Schema::InputObject || self < GraphQL::Schema::Directive
43
- "self."
44
- elsif self < GraphQL::Schema::Resolver
45
- ""
46
- else
47
- raise "Unexpected argument owner: #{self}"
48
- end
49
- if loads && arg_defn.type.list?
50
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
51
- def #{method_owner}load_#{arg_defn.keyword}(values, context = nil)
52
- argument = get_argument("#{arg_defn.graphql_name}")
53
- (context || self.context).schema.after_lazy(values) do |values2|
54
- GraphQL::Execution::Lazy.all(values2.map { |value| load_application_object(argument, value, context || self.context) })
55
- end
56
- end
57
- RUBY
58
- elsif loads
59
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
60
- def #{method_owner}load_#{arg_defn.keyword}(value, context = nil)
61
- argument = get_argument("#{arg_defn.graphql_name}")
62
- load_application_object(argument, value, context || self.context)
63
- end
64
- RUBY
65
- else
66
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
67
- def #{method_owner}load_#{arg_defn.keyword}(value, _context = nil)
68
- value
69
- end
70
- RUBY
71
- end
72
- end
73
41
  arg_defn
74
42
  end
75
43
 
@@ -108,15 +76,7 @@ module GraphQL
108
76
  end
109
77
 
110
78
  # @return [Hash<String => GraphQL::Schema::Argument] Arguments defined on this thing, keyed by name. Includes inherited definitions
111
- def arguments(context = GraphQL::Query::NullContext)
112
- inherited_arguments = if self.is_a?(Class) && superclass.respond_to?(:arguments)
113
- superclass.arguments(context)
114
- elsif defined?(@resolver_class) && @resolver_class
115
- @resolver_class.field_arguments(context)
116
- else
117
- nil
118
- end
119
- # Local definitions override inherited ones
79
+ def arguments(context = GraphQL::Query::NullContext.instance)
120
80
  if own_arguments.any?
121
81
  own_arguments_that_apply = {}
122
82
  own_arguments.each do |name, args_entry|
@@ -125,70 +85,132 @@ module GraphQL
125
85
  end
126
86
  end
127
87
  end
88
+ # might be nil if there are actually no arguments
89
+ own_arguments_that_apply || own_arguments
90
+ end
91
+
92
+ def any_arguments?
93
+ own_arguments.any?
94
+ end
95
+
96
+ module ClassConfigured
97
+ def inherited(child_class)
98
+ super
99
+ child_class.extend(InheritedArguments)
100
+ end
128
101
 
129
- if inherited_arguments
130
- if own_arguments_that_apply
131
- inherited_arguments.merge(own_arguments_that_apply)
132
- else
133
- inherited_arguments
102
+ module InheritedArguments
103
+ def arguments(context = GraphQL::Query::NullContext.instance)
104
+ own_arguments = super
105
+ inherited_arguments = superclass.arguments(context)
106
+
107
+ if own_arguments.any?
108
+ if inherited_arguments.any?
109
+ # Local definitions override inherited ones
110
+ inherited_arguments.merge(own_arguments)
111
+ else
112
+ own_arguments
113
+ end
114
+ else
115
+ inherited_arguments
116
+ end
117
+ end
118
+
119
+ def any_arguments?
120
+ super || superclass.any_arguments?
121
+ end
122
+
123
+ def all_argument_definitions
124
+ all_defns = {}
125
+ ancestors.reverse_each do |ancestor|
126
+ if ancestor.respond_to?(:own_arguments)
127
+ all_defns.merge!(ancestor.own_arguments)
128
+ end
129
+ end
130
+ all_defns = all_defns.values
131
+ all_defns.flatten!
132
+ all_defns
133
+ end
134
+
135
+
136
+ def get_argument(argument_name, context = GraphQL::Query::NullContext.instance)
137
+ warden = Warden.from_context(context)
138
+ skip_visible = context.respond_to?(:types) && context.types.is_a?(GraphQL::Schema::Subset)
139
+ for ancestor in ancestors
140
+ if ancestor.respond_to?(:own_arguments) &&
141
+ (a = ancestor.own_arguments[argument_name]) &&
142
+ (skip_visible || (a = Warden.visible_entry?(:visible_argument?, a, context, warden)))
143
+ return a
144
+ end
145
+ end
146
+ nil
134
147
  end
135
- else
136
- # might be nil if there are actually no arguments
137
- own_arguments_that_apply || own_arguments
138
148
  end
139
149
  end
140
150
 
141
- def all_argument_definitions
142
- if self.is_a?(Class)
143
- all_defns = {}
144
- ancestors.reverse_each do |ancestor|
145
- if ancestor.respond_to?(:own_arguments)
146
- all_defns.merge!(ancestor.own_arguments)
151
+ module FieldConfigured
152
+ def arguments(context = GraphQL::Query::NullContext.instance)
153
+ own_arguments = super
154
+ if @resolver_class
155
+ inherited_arguments = @resolver_class.field_arguments(context)
156
+ if own_arguments.any?
157
+ if inherited_arguments.any?
158
+ inherited_arguments.merge(own_arguments)
159
+ else
160
+ own_arguments
161
+ end
162
+ else
163
+ inherited_arguments
147
164
  end
165
+ else
166
+ own_arguments
148
167
  end
149
- elsif defined?(@resolver_class) && @resolver_class
150
- all_defns = {}
151
- @resolver_class.all_field_argument_definitions.each do |arg_defn|
152
- key = arg_defn.graphql_name
153
- case (current_value = all_defns[key])
154
- when nil
155
- all_defns[key] = arg_defn
156
- when Array
157
- current_value << arg_defn
158
- when GraphQL::Schema::Argument
159
- all_defns[key] = [current_value, arg_defn]
160
- else
161
- raise "Invariant: Unexpected argument definition, #{current_value.class}: #{current_value.inspect}"
168
+ end
169
+
170
+ def any_arguments?
171
+ super || (@resolver_class && @resolver_class.any_field_arguments?)
172
+ end
173
+
174
+ def all_argument_definitions
175
+ if @resolver_class
176
+ all_defns = {}
177
+ @resolver_class.all_field_argument_definitions.each do |arg_defn|
178
+ key = arg_defn.graphql_name
179
+ case (current_value = all_defns[key])
180
+ when nil
181
+ all_defns[key] = arg_defn
182
+ when Array
183
+ current_value << arg_defn
184
+ when GraphQL::Schema::Argument
185
+ all_defns[key] = [current_value, arg_defn]
186
+ else
187
+ raise "Invariant: Unexpected argument definition, #{current_value.class}: #{current_value.inspect}"
188
+ end
162
189
  end
190
+ all_defns.merge!(own_arguments)
191
+ all_defns = all_defns.values
192
+ all_defns.flatten!
193
+ all_defns
194
+ else
195
+ super
163
196
  end
164
- all_defns.merge!(own_arguments)
165
- else
166
- all_defns = own_arguments
167
197
  end
168
- all_defns = all_defns.values
198
+ end
199
+
200
+ def all_argument_definitions
201
+ all_defns = own_arguments.values
169
202
  all_defns.flatten!
170
203
  all_defns
171
204
  end
172
205
 
173
206
  # @return [GraphQL::Schema::Argument, nil] Argument defined on this thing, fetched by name.
174
- def get_argument(argument_name, context = GraphQL::Query::NullContext)
207
+ def get_argument(argument_name, context = GraphQL::Query::NullContext.instance)
175
208
  warden = Warden.from_context(context)
176
- if !self.is_a?(Class)
177
- if (arg_config = own_arguments[argument_name]) && (visible_arg = Warden.visible_entry?(:visible_argument?, arg_config, context, warden))
178
- visible_arg
179
- elsif defined?(@resolver_class) && @resolver_class
180
- @resolver_class.get_field_argument(argument_name, context)
181
- else
182
- nil
183
- end
209
+ if (arg_config = own_arguments[argument_name]) && ((context.respond_to?(:types) && context.types.is_a?(GraphQL::Schema::Subset)) || (visible_arg = Warden.visible_entry?(:visible_argument?, arg_config, context, warden)))
210
+ visible_arg || arg_config
211
+ elsif defined?(@resolver_class) && @resolver_class
212
+ @resolver_class.get_field_argument(argument_name, context)
184
213
  else
185
- for ancestor in ancestors
186
- if ancestor.respond_to?(:own_arguments) &&
187
- (a = ancestor.own_arguments[argument_name]) &&
188
- (a = Warden.visible_entry?(:visible_argument?, a, context, warden))
189
- return a
190
- end
191
- end
192
214
  nil
193
215
  end
194
216
  end
@@ -205,11 +227,11 @@ module GraphQL
205
227
  #
206
228
  # @param values [Hash<String, Object>]
207
229
  # @param context [GraphQL::Query::Context]
208
- # @yield [Interpreter::Arguments, Execution::Lazy<Interpeter::Arguments>]
209
- # @return [Interpreter::Arguments, Execution::Lazy<Interpeter::Arguments>]
230
+ # @yield [Interpreter::Arguments, Execution::Lazy<Interpreter::Arguments>]
231
+ # @return [Interpreter::Arguments, Execution::Lazy<Interpreter::Arguments>]
210
232
  def coerce_arguments(parent_object, values, context, &block)
211
233
  # Cache this hash to avoid re-merging it
212
- arg_defns = self.arguments(context)
234
+ arg_defns = context.types.arguments(self)
213
235
  total_args_count = arg_defns.size
214
236
 
215
237
  finished_args = nil
@@ -223,7 +245,7 @@ module GraphQL
223
245
  argument_values = {}
224
246
  resolved_args_count = 0
225
247
  raised_error = false
226
- arg_defns.each do |arg_name, arg_defn|
248
+ arg_defns.each do |arg_defn|
227
249
  context.dataloader.append_job do
228
250
  begin
229
251
  arg_defn.coerce_into_values(parent_object, values, context, argument_values)
@@ -265,7 +287,12 @@ module GraphQL
265
287
  # but not for directives.
266
288
  # TODO apply static validations on schema definitions?
267
289
  def validate_directive_argument(arg_defn, value)
268
- if arg_defn.owner.is_a?(Class) && arg_defn.owner < GraphQL::Schema::Directive
290
+ # this is only implemented on directives.
291
+ nil
292
+ end
293
+
294
+ module HasDirectiveArguments
295
+ def validate_directive_argument(arg_defn, value)
269
296
  if value.nil? && arg_defn.type.non_null?
270
297
  raise ArgumentError, "#{arg_defn.path} is required, but no value was given"
271
298
  end
@@ -273,9 +300,11 @@ module GraphQL
273
300
  end
274
301
 
275
302
  def arguments_statically_coercible?
276
- return @arguments_statically_coercible if defined?(@arguments_statically_coercible)
277
-
278
- @arguments_statically_coercible = all_argument_definitions.all?(&:statically_coercible?)
303
+ if defined?(@arguments_statically_coercible) && !@arguments_statically_coercible.nil?
304
+ @arguments_statically_coercible
305
+ else
306
+ @arguments_statically_coercible = all_argument_definitions.all?(&:statically_coercible?)
307
+ end
279
308
  end
280
309
 
281
310
  module ArgumentClassAccessor
@@ -316,43 +345,54 @@ module GraphQL
316
345
  end
317
346
 
318
347
  def authorize_application_object(argument, id, context, loaded_application_object)
319
- context.schema.after_lazy(loaded_application_object) do |application_object|
348
+ context.query.after_lazy(loaded_application_object) do |application_object|
320
349
  if application_object.nil?
321
- err = GraphQL::LoadApplicationObjectFailedError.new(argument: argument, id: id, object: application_object)
322
- load_application_object_failed(err)
350
+ err = GraphQL::LoadApplicationObjectFailedError.new(context: context, argument: argument, id: id, object: application_object)
351
+ application_object = load_application_object_failed(err)
323
352
  end
324
353
  # Double-check that the located object is actually of this type
325
354
  # (Don't want to allow arbitrary access to objects this way)
326
- maybe_lazy_resolve_type = context.schema.resolve_type(argument.loads, application_object, context)
327
- context.schema.after_lazy(maybe_lazy_resolve_type) do |resolve_type_result|
328
- if resolve_type_result.is_a?(Array) && resolve_type_result.size == 2
329
- application_object_type, application_object = resolve_type_result
330
- else
331
- application_object_type = resolve_type_result
332
- # application_object is already assigned
333
- end
334
- possible_object_types = context.warden.possible_types(argument.loads)
335
- if !possible_object_types.include?(application_object_type)
336
- err = GraphQL::LoadApplicationObjectFailedError.new(argument: argument, id: id, object: application_object)
337
- load_application_object_failed(err)
338
- else
339
- # This object was loaded successfully
340
- # and resolved to the right type,
341
- # now apply the `.authorized?` class method if there is one
342
- context.schema.after_lazy(application_object_type.authorized?(application_object, context)) do |authed|
343
- if authed
344
- application_object
345
- else
346
- err = GraphQL::UnauthorizedError.new(
347
- object: application_object,
348
- type: application_object_type,
349
- context: context,
350
- )
351
- if self.respond_to?(:unauthorized_object)
352
- err.set_backtrace(caller)
353
- unauthorized_object(err)
355
+ if application_object.nil?
356
+ nil
357
+ else
358
+ maybe_lazy_resolve_type = context.schema.resolve_type(argument.loads, application_object, context)
359
+ context.query.after_lazy(maybe_lazy_resolve_type) do |resolve_type_result|
360
+ if resolve_type_result.is_a?(Array) && resolve_type_result.size == 2
361
+ application_object_type, application_object = resolve_type_result
362
+ else
363
+ application_object_type = resolve_type_result
364
+ # application_object is already assigned
365
+ end
366
+
367
+ if !(
368
+ context.types.possible_types(argument.loads).include?(application_object_type) ||
369
+ context.types.loadable?(argument.loads, context)
370
+ )
371
+ err = GraphQL::LoadApplicationObjectFailedError.new(context: context, argument: argument, id: id, object: application_object)
372
+ application_object = load_application_object_failed(err)
373
+ end
374
+
375
+ if application_object.nil?
376
+ nil
377
+ else
378
+ # This object was loaded successfully
379
+ # and resolved to the right type,
380
+ # now apply the `.authorized?` class method if there is one
381
+ context.query.after_lazy(application_object_type.authorized?(application_object, context)) do |authed|
382
+ if authed
383
+ application_object
354
384
  else
355
- raise err
385
+ err = GraphQL::UnauthorizedError.new(
386
+ object: application_object,
387
+ type: application_object_type,
388
+ context: context,
389
+ )
390
+ if self.respond_to?(:unauthorized_object)
391
+ err.set_backtrace(caller)
392
+ unauthorized_object(err)
393
+ else
394
+ raise err
395
+ end
356
396
  end
357
397
  end
358
398
  end
@@ -366,7 +406,7 @@ module GraphQL
366
406
  end
367
407
  end
368
408
 
369
- NO_ARGUMENTS = {}.freeze
409
+ NO_ARGUMENTS = GraphQL::EmptyObjects::EMPTY_HASH
370
410
  def own_arguments
371
411
  @own_arguments || NO_ARGUMENTS
372
412
  end
@@ -3,6 +3,16 @@ module GraphQL
3
3
  class Schema
4
4
  class Member
5
5
  module HasAstNode
6
+ def self.extended(child_cls)
7
+ super
8
+ child_cls.ast_node = nil
9
+ end
10
+
11
+ def inherited(child_cls)
12
+ super
13
+ child_cls.ast_node = nil
14
+ end
15
+
6
16
  # If this schema was parsed from a `.graphql` file (or other SDL),
7
17
  # this is the AST node that defined this part of the schema.
8
18
  def ast_node(new_ast_node = nil)
@@ -14,6 +24,8 @@ module GraphQL
14
24
  nil
15
25
  end
16
26
  end
27
+
28
+ attr_writer :ast_node
17
29
  end
18
30
  end
19
31
  end
@@ -5,17 +5,16 @@ module GraphQL
5
5
  class Member
6
6
  module HasDeprecationReason
7
7
  # @return [String, nil] Explains why this member was deprecated (if present, this will be marked deprecated in introspection)
8
- def deprecation_reason
9
- dir = self.directives.find { |d| d.is_a?(GraphQL::Schema::Directive::Deprecated) }
10
- dir && dir.arguments[:reason] # rubocop:disable Development/ContextIsPassedCop -- definition-related
11
- end
8
+ attr_reader :deprecation_reason
12
9
 
13
10
  # Set the deprecation reason for this member, or remove it by assigning `nil`
14
11
  # @param text [String, nil]
15
12
  def deprecation_reason=(text)
13
+ @deprecation_reason = text
16
14
  if text.nil?
17
15
  remove_directive(GraphQL::Schema::Directive::Deprecated)
18
16
  else
17
+ # This removes a previously-attached directive, if there is one:
19
18
  directive(GraphQL::Schema::Directive::Deprecated, reason: text)
20
19
  end
21
20
  end
@@ -4,6 +4,16 @@ module GraphQL
4
4
  class Schema
5
5
  class Member
6
6
  module HasDirectives
7
+ def self.extended(child_cls)
8
+ super
9
+ child_cls.module_eval { self.own_directives = nil }
10
+ end
11
+
12
+ def inherited(child_cls)
13
+ super
14
+ child_cls.own_directives = nil
15
+ end
16
+
7
17
  # Create an instance of `dir_class` for `self`, using `options`.
8
18
  #
9
19
  # It removes a previously-attached instance of `dir_class`, if there is one.
@@ -11,8 +21,7 @@ module GraphQL
11
21
  # @return [void]
12
22
  def directive(dir_class, **options)
13
23
  @own_directives ||= []
14
- remove_directive(dir_class) unless dir_class.repeatable?
15
- @own_directives << dir_class.new(self, **options)
24
+ HasDirectives.add_directive(self, @own_directives, dir_class, options)
16
25
  nil
17
26
  end
18
27
 
@@ -20,78 +29,89 @@ module GraphQL
20
29
  # @param dir_class [Class<GraphQL::Schema::Directive>]
21
30
  # @return [viod]
22
31
  def remove_directive(dir_class)
23
- @own_directives && @own_directives.reject! { |d| d.is_a?(dir_class) }
32
+ HasDirectives.remove_directive(@own_directives, dir_class)
24
33
  nil
25
34
  end
26
35
 
27
- NO_DIRECTIVES = [].freeze
28
-
29
36
  def directives
30
- case self
31
- when Class
32
- inherited_directives = if superclass.respond_to?(:directives)
33
- superclass.directives
34
- else
35
- NO_DIRECTIVES
36
- end
37
- if inherited_directives.any? && @own_directives
38
- dirs = []
39
- merge_directives(dirs, inherited_directives)
40
- merge_directives(dirs, @own_directives)
41
- dirs
42
- elsif @own_directives
43
- @own_directives
44
- elsif inherited_directives.any?
45
- inherited_directives
46
- else
47
- NO_DIRECTIVES
48
- end
49
- when Module
50
- dirs = nil
51
- self.ancestors.reverse_each do |ancestor|
52
- if ancestor.respond_to?(:own_directives) &&
53
- (anc_dirs = ancestor.own_directives).any?
37
+ HasDirectives.get_directives(self, @own_directives, :directives)
38
+ end
39
+
40
+ class << self
41
+ def add_directive(schema_member, directives, directive_class, directive_options)
42
+ remove_directive(directives, directive_class) unless directive_class.repeatable?
43
+ directives << directive_class.new(schema_member, **directive_options)
44
+ end
45
+
46
+ def remove_directive(directives, directive_class)
47
+ directives && directives.reject! { |d| d.is_a?(directive_class) }
48
+ end
49
+
50
+ def get_directives(schema_member, directives, directives_method)
51
+ case schema_member
52
+ when Class
53
+ inherited_directives = if schema_member.superclass.respond_to?(directives_method)
54
+ get_directives(schema_member.superclass, schema_member.superclass.public_send(directives_method), directives_method)
55
+ else
56
+ GraphQL::EmptyObjects::EMPTY_ARRAY
57
+ end
58
+ if inherited_directives.any? && directives
59
+ dirs = []
60
+ merge_directives(dirs, inherited_directives)
61
+ merge_directives(dirs, directives)
62
+ dirs
63
+ elsif directives
64
+ directives
65
+ elsif inherited_directives.any?
66
+ inherited_directives
67
+ else
68
+ GraphQL::EmptyObjects::EMPTY_ARRAY
69
+ end
70
+ when Module
71
+ dirs = nil
72
+ schema_member.ancestors.reverse_each do |ancestor|
73
+ if ancestor.respond_to?(:own_directives) &&
74
+ (anc_dirs = ancestor.own_directives).any?
75
+ dirs ||= []
76
+ merge_directives(dirs, anc_dirs)
77
+ end
78
+ end
79
+ if directives
54
80
  dirs ||= []
55
- merge_directives(dirs, anc_dirs)
81
+ merge_directives(dirs, directives)
56
82
  end
83
+ dirs || GraphQL::EmptyObjects::EMPTY_ARRAY
84
+ when HasDirectives
85
+ directives || GraphQL::EmptyObjects::EMPTY_ARRAY
86
+ else
87
+ raise "Invariant: how could #{schema_member} not be a Class, Module, or instance of HasDirectives?"
57
88
  end
58
- if own_directives
59
- dirs ||= []
60
- merge_directives(dirs, own_directives)
61
- end
62
- dirs || NO_DIRECTIVES
63
- when HasDirectives
64
- @own_directives || NO_DIRECTIVES
65
- else
66
- raise "Invariant: how could #{self} not be a Class, Module, or instance of HasDirectives?"
67
89
  end
68
- end
69
-
70
- protected
71
-
72
- def own_directives
73
- @own_directives
74
- end
75
90
 
76
- private
91
+ private
77
92
 
78
- # Modify `target` by adding items from `dirs` such that:
79
- # - Any name conflict is overriden by the incoming member of `dirs`
80
- # - Any other member of `dirs` is appended
81
- # @param target [Array<GraphQL::Schema::Directive>]
82
- # @param dirs [Array<GraphQL::Schema::Directive>]
83
- # @return [void]
84
- def merge_directives(target, dirs)
85
- dirs.each do |dir|
86
- if (idx = target.find_index { |d| d.graphql_name == dir.graphql_name })
87
- target.slice!(idx)
88
- target.insert(idx, dir)
89
- else
90
- target << dir
93
+ # Modify `target` by adding items from `dirs` such that:
94
+ # - Any name conflict is overridden by the incoming member of `dirs`
95
+ # - Any other member of `dirs` is appended
96
+ # @param target [Array<GraphQL::Schema::Directive>]
97
+ # @param dirs [Array<GraphQL::Schema::Directive>]
98
+ # @return [void]
99
+ def merge_directives(target, dirs)
100
+ dirs.each do |dir|
101
+ if (idx = target.find_index { |d| d.graphql_name == dir.graphql_name })
102
+ target.slice!(idx)
103
+ target.insert(idx, dir)
104
+ else
105
+ target << dir
106
+ end
91
107
  end
108
+ nil
92
109
  end
93
- nil
94
110
  end
111
+
112
+ protected
113
+
114
+ attr_accessor :own_directives
95
115
  end
96
116
  end
97
117
  end