graphql 2.0.13 → 2.3.10

Sign up to get free protection for your applications and to get access to all the features.
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