graphql 1.13.19 → 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 (256) 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 +162 -119
  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/dynamic_fields.rb +3 -8
  28. data/lib/graphql/introspection/entry_points.rb +2 -15
  29. data/lib/graphql/introspection/type_type.rb +8 -1
  30. data/lib/graphql/introspection.rb +4 -3
  31. data/lib/graphql/language/document_from_schema_definition.rb +18 -35
  32. data/lib/graphql/language/lexer.rb +216 -1488
  33. data/lib/graphql/language/lexer.ri +744 -0
  34. data/lib/graphql/language/nodes.rb +41 -33
  35. data/lib/graphql/language/parser.rb +375 -363
  36. data/lib/graphql/language/parser.y +48 -43
  37. data/lib/graphql/language/printer.rb +37 -21
  38. data/lib/graphql/language/visitor.rb +191 -83
  39. data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
  40. data/lib/graphql/pagination/array_connection.rb +4 -2
  41. data/lib/graphql/pagination/connection.rb +31 -4
  42. data/lib/graphql/pagination/connections.rb +3 -28
  43. data/lib/graphql/pagination/relation_connection.rb +2 -0
  44. data/lib/graphql/query/context.rb +155 -196
  45. data/lib/graphql/query/input_validation_result.rb +1 -1
  46. data/lib/graphql/query/null_context.rb +0 -3
  47. data/lib/graphql/query/validation_pipeline.rb +10 -34
  48. data/lib/graphql/query/variables.rb +7 -20
  49. data/lib/graphql/query.rb +32 -42
  50. data/lib/graphql/railtie.rb +0 -104
  51. data/lib/graphql/rake_task/validate.rb +1 -1
  52. data/lib/graphql/rake_task.rb +29 -1
  53. data/lib/graphql/relay/range_add.rb +9 -20
  54. data/lib/graphql/relay.rb +0 -15
  55. data/lib/graphql/schema/addition.rb +7 -9
  56. data/lib/graphql/schema/argument.rb +36 -43
  57. data/lib/graphql/schema/build_from_definition.rb +32 -18
  58. data/lib/graphql/schema/directive/one_of.rb +12 -0
  59. data/lib/graphql/schema/directive/transform.rb +1 -1
  60. data/lib/graphql/schema/directive.rb +11 -22
  61. data/lib/graphql/schema/enum.rb +28 -39
  62. data/lib/graphql/schema/enum_value.rb +5 -25
  63. data/lib/graphql/schema/field/connection_extension.rb +4 -0
  64. data/lib/graphql/schema/field.rb +214 -327
  65. data/lib/graphql/schema/input_object.rb +56 -67
  66. data/lib/graphql/schema/interface.rb +0 -35
  67. data/lib/graphql/schema/introspection_system.rb +3 -8
  68. data/lib/graphql/schema/late_bound_type.rb +8 -2
  69. data/lib/graphql/schema/list.rb +0 -6
  70. data/lib/graphql/schema/loader.rb +1 -2
  71. data/lib/graphql/schema/member/base_dsl_methods.rb +15 -19
  72. data/lib/graphql/schema/member/build_type.rb +5 -7
  73. data/lib/graphql/schema/member/has_arguments.rb +144 -53
  74. data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
  75. data/lib/graphql/schema/member/has_directives.rb +71 -56
  76. data/lib/graphql/schema/member/has_fields.rb +15 -3
  77. data/lib/graphql/schema/member/has_interfaces.rb +47 -18
  78. data/lib/graphql/schema/member/has_validators.rb +31 -5
  79. data/lib/graphql/schema/member/relay_shortcuts.rb +28 -2
  80. data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
  81. data/lib/graphql/schema/member/validates_input.rb +1 -1
  82. data/lib/graphql/schema/member.rb +0 -6
  83. data/lib/graphql/schema/mutation.rb +0 -9
  84. data/lib/graphql/schema/non_null.rb +1 -7
  85. data/lib/graphql/schema/object.rb +15 -52
  86. data/lib/graphql/schema/relay_classic_mutation.rb +53 -42
  87. data/lib/graphql/schema/resolver/has_payload_type.rb +20 -10
  88. data/lib/graphql/schema/resolver.rb +41 -42
  89. data/lib/graphql/schema/scalar.rb +7 -22
  90. data/lib/graphql/schema/subscription.rb +0 -7
  91. data/lib/graphql/schema/timeout.rb +24 -28
  92. data/lib/graphql/schema/type_membership.rb +3 -0
  93. data/lib/graphql/schema/union.rb +10 -17
  94. data/lib/graphql/schema/warden.rb +23 -6
  95. data/lib/graphql/schema/wrapper.rb +0 -5
  96. data/lib/graphql/schema.rb +240 -968
  97. data/lib/graphql/static_validation/all_rules.rb +1 -0
  98. data/lib/graphql/static_validation/base_visitor.rb +4 -21
  99. data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
  100. data/lib/graphql/static_validation/error.rb +2 -2
  101. data/lib/graphql/static_validation/literal_validator.rb +19 -1
  102. data/lib/graphql/static_validation/rules/directives_are_defined.rb +11 -5
  103. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +12 -12
  104. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  105. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  106. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +12 -6
  107. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -1
  108. data/lib/graphql/static_validation/validator.rb +3 -25
  109. data/lib/graphql/static_validation.rb +0 -2
  110. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -1
  111. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +38 -1
  112. data/lib/graphql/subscriptions/event.rb +3 -8
  113. data/lib/graphql/subscriptions/instrumentation.rb +0 -51
  114. data/lib/graphql/subscriptions.rb +32 -20
  115. data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
  116. data/lib/graphql/tracing/appoptics_trace.rb +231 -0
  117. data/lib/graphql/tracing/appsignal_trace.rb +66 -0
  118. data/lib/graphql/tracing/data_dog_trace.rb +148 -0
  119. data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
  120. data/lib/graphql/tracing/new_relic_trace.rb +75 -0
  121. data/lib/graphql/tracing/notifications_trace.rb +41 -0
  122. data/lib/graphql/tracing/platform_trace.rb +107 -0
  123. data/lib/graphql/tracing/platform_tracing.rb +26 -41
  124. data/lib/graphql/tracing/prometheus_trace.rb +89 -0
  125. data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
  126. data/lib/graphql/tracing/scout_trace.rb +72 -0
  127. data/lib/graphql/tracing/statsd_trace.rb +56 -0
  128. data/lib/graphql/tracing.rb +136 -40
  129. data/lib/graphql/type_kinds.rb +6 -3
  130. data/lib/graphql/types/iso_8601_date.rb +4 -1
  131. data/lib/graphql/types/iso_8601_date_time.rb +4 -0
  132. data/lib/graphql/types/relay/base_connection.rb +16 -6
  133. data/lib/graphql/types/relay/connection_behaviors.rb +5 -25
  134. data/lib/graphql/types/relay/default_relay.rb +5 -9
  135. data/lib/graphql/types/relay/edge_behaviors.rb +1 -4
  136. data/lib/graphql/types/relay/node_behaviors.rb +5 -1
  137. data/lib/graphql/types/relay.rb +0 -2
  138. data/lib/graphql/types/string.rb +1 -1
  139. data/lib/graphql/version.rb +1 -1
  140. data/lib/graphql.rb +11 -72
  141. metadata +31 -132
  142. data/lib/graphql/analysis/analyze_query.rb +0 -98
  143. data/lib/graphql/analysis/field_usage.rb +0 -45
  144. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  145. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  146. data/lib/graphql/analysis/query_complexity.rb +0 -88
  147. data/lib/graphql/analysis/query_depth.rb +0 -43
  148. data/lib/graphql/analysis/reducer_state.rb +0 -48
  149. data/lib/graphql/argument.rb +0 -131
  150. data/lib/graphql/authorization.rb +0 -82
  151. data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
  152. data/lib/graphql/backwards_compatibility.rb +0 -61
  153. data/lib/graphql/base_type.rb +0 -232
  154. data/lib/graphql/boolean_type.rb +0 -2
  155. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  156. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  157. data/lib/graphql/compatibility/execution_specification.rb +0 -436
  158. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  159. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
  160. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
  161. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  162. data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
  163. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
  164. data/lib/graphql/compatibility.rb +0 -5
  165. data/lib/graphql/define/assign_argument.rb +0 -12
  166. data/lib/graphql/define/assign_connection.rb +0 -13
  167. data/lib/graphql/define/assign_enum_value.rb +0 -18
  168. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  169. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  170. data/lib/graphql/define/assign_object_field.rb +0 -42
  171. data/lib/graphql/define/defined_object_proxy.rb +0 -53
  172. data/lib/graphql/define/instance_definable.rb +0 -255
  173. data/lib/graphql/define/no_definition_error.rb +0 -7
  174. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  175. data/lib/graphql/define/type_definer.rb +0 -31
  176. data/lib/graphql/define.rb +0 -31
  177. data/lib/graphql/deprecated_dsl.rb +0 -55
  178. data/lib/graphql/directive/deprecated_directive.rb +0 -2
  179. data/lib/graphql/directive/include_directive.rb +0 -2
  180. data/lib/graphql/directive/skip_directive.rb +0 -2
  181. data/lib/graphql/directive.rb +0 -107
  182. data/lib/graphql/enum_type.rb +0 -133
  183. data/lib/graphql/execution/execute.rb +0 -333
  184. data/lib/graphql/execution/flatten.rb +0 -40
  185. data/lib/graphql/execution/instrumentation.rb +0 -92
  186. data/lib/graphql/execution/lazy/resolve.rb +0 -91
  187. data/lib/graphql/execution/typecast.rb +0 -50
  188. data/lib/graphql/field/resolve.rb +0 -59
  189. data/lib/graphql/field.rb +0 -226
  190. data/lib/graphql/float_type.rb +0 -2
  191. data/lib/graphql/function.rb +0 -128
  192. data/lib/graphql/id_type.rb +0 -2
  193. data/lib/graphql/input_object_type.rb +0 -138
  194. data/lib/graphql/int_type.rb +0 -2
  195. data/lib/graphql/interface_type.rb +0 -72
  196. data/lib/graphql/internal_representation/document.rb +0 -27
  197. data/lib/graphql/internal_representation/node.rb +0 -206
  198. data/lib/graphql/internal_representation/print.rb +0 -51
  199. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  200. data/lib/graphql/internal_representation/scope.rb +0 -88
  201. data/lib/graphql/internal_representation/visit.rb +0 -36
  202. data/lib/graphql/internal_representation.rb +0 -7
  203. data/lib/graphql/language/lexer.rl +0 -260
  204. data/lib/graphql/list_type.rb +0 -80
  205. data/lib/graphql/non_null_type.rb +0 -71
  206. data/lib/graphql/object_type.rb +0 -130
  207. data/lib/graphql/query/arguments.rb +0 -189
  208. data/lib/graphql/query/arguments_cache.rb +0 -24
  209. data/lib/graphql/query/executor.rb +0 -52
  210. data/lib/graphql/query/literal_input.rb +0 -136
  211. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  212. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  213. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  214. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  215. data/lib/graphql/query/serial_execution.rb +0 -40
  216. data/lib/graphql/relay/array_connection.rb +0 -83
  217. data/lib/graphql/relay/base_connection.rb +0 -189
  218. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  219. data/lib/graphql/relay/connection_resolve.rb +0 -43
  220. data/lib/graphql/relay/connection_type.rb +0 -54
  221. data/lib/graphql/relay/edge.rb +0 -27
  222. data/lib/graphql/relay/edge_type.rb +0 -19
  223. data/lib/graphql/relay/edges_instrumentation.rb +0 -39
  224. data/lib/graphql/relay/global_id_resolve.rb +0 -17
  225. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  226. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  227. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  228. data/lib/graphql/relay/mutation/result.rb +0 -38
  229. data/lib/graphql/relay/mutation.rb +0 -106
  230. data/lib/graphql/relay/node.rb +0 -39
  231. data/lib/graphql/relay/page_info.rb +0 -7
  232. data/lib/graphql/relay/relation_connection.rb +0 -188
  233. data/lib/graphql/relay/type_extensions.rb +0 -32
  234. data/lib/graphql/scalar_type.rb +0 -91
  235. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  236. data/lib/graphql/schema/default_parse_error.rb +0 -10
  237. data/lib/graphql/schema/default_type_error.rb +0 -17
  238. data/lib/graphql/schema/member/accepts_definition.rb +0 -164
  239. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -58
  240. data/lib/graphql/schema/member/instrumentation.rb +0 -131
  241. data/lib/graphql/schema/middleware_chain.rb +0 -82
  242. data/lib/graphql/schema/possible_types.rb +0 -44
  243. data/lib/graphql/schema/rescue_middleware.rb +0 -60
  244. data/lib/graphql/schema/timeout_middleware.rb +0 -88
  245. data/lib/graphql/schema/traversal.rb +0 -228
  246. data/lib/graphql/schema/validation.rb +0 -313
  247. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  248. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  249. data/lib/graphql/string_type.rb +0 -2
  250. data/lib/graphql/subscriptions/subscription_root.rb +0 -76
  251. data/lib/graphql/tracing/skylight_tracing.rb +0 -70
  252. data/lib/graphql/types/relay/node_field.rb +0 -24
  253. data/lib/graphql/types/relay/nodes_field.rb +0 -43
  254. data/lib/graphql/union_type.rb +0 -115
  255. data/lib/graphql/upgrader/member.rb +0 -937
  256. data/lib/graphql/upgrader/schema.rb +0 -38
@@ -11,10 +11,11 @@ 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
17
- # @return [GraphQL::Schema::Argument] An instance of {arguments_class}, created from `*args`
18
+ # @return [GraphQL::Schema::Argument] An instance of {argument_class}, created from `*args`
18
19
  def argument(*args, **kwargs, &block)
19
20
  kwargs[:owner] = self
20
21
  loads = kwargs[:loads]
@@ -78,24 +79,37 @@ module GraphQL
78
79
  # @return [GraphQL::Schema::Argument]
79
80
  def add_argument(arg_defn)
80
81
  @own_arguments ||= {}
81
- prev_defn = own_arguments[arg_defn.name]
82
+ prev_defn = @own_arguments[arg_defn.name]
82
83
  case prev_defn
83
84
  when nil
84
- own_arguments[arg_defn.name] = arg_defn
85
+ @own_arguments[arg_defn.name] = arg_defn
85
86
  when Array
86
87
  prev_defn << arg_defn
87
88
  when GraphQL::Schema::Argument
88
- own_arguments[arg_defn.name] = [prev_defn, arg_defn]
89
+ @own_arguments[arg_defn.name] = [prev_defn, arg_defn]
89
90
  else
90
91
  raise "Invariant: unexpected `@own_arguments[#{arg_defn.name.inspect}]`: #{prev_defn.inspect}"
91
92
  end
92
93
  arg_defn
93
94
  end
94
95
 
96
+ def remove_argument(arg_defn)
97
+ prev_defn = @own_arguments[arg_defn.name]
98
+ case prev_defn
99
+ when nil
100
+ # done
101
+ when Array
102
+ prev_defn.delete(arg_defn)
103
+ when GraphQL::Schema::Argument
104
+ @own_arguments.delete(arg_defn.name)
105
+ else
106
+ raise "Invariant: unexpected `@own_arguments[#{arg_defn.name.inspect}]`: #{prev_defn.inspect}"
107
+ end
108
+ nil
109
+ end
110
+
95
111
  # @return [Hash<String => GraphQL::Schema::Argument] Arguments defined on this thing, keyed by name. Includes inherited definitions
96
112
  def arguments(context = GraphQL::Query::NullContext)
97
- inherited_arguments = ((self.is_a?(Class) && superclass.respond_to?(:arguments)) ? superclass.arguments(context) : nil)
98
- # Local definitions override inherited ones
99
113
  if own_arguments.any?
100
114
  own_arguments_that_apply = {}
101
115
  own_arguments.each do |name, args_entry|
@@ -104,31 +118,107 @@ module GraphQL
104
118
  end
105
119
  end
106
120
  end
121
+ # might be nil if there are actually no arguments
122
+ own_arguments_that_apply || own_arguments
123
+ end
124
+
125
+ module ClassConfigured
126
+ def inherited(child_class)
127
+ super
128
+ child_class.extend(InheritedArguments)
129
+ end
107
130
 
108
- if inherited_arguments
109
- if own_arguments_that_apply
110
- inherited_arguments.merge(own_arguments_that_apply)
111
- else
112
- inherited_arguments
131
+ module InheritedArguments
132
+ def arguments(context = GraphQL::Query::NullContext)
133
+ own_arguments = super
134
+ inherited_arguments = superclass.arguments(context)
135
+
136
+ if own_arguments.any?
137
+ if inherited_arguments.any?
138
+ # Local definitions override inherited ones
139
+ inherited_arguments.merge(own_arguments)
140
+ else
141
+ own_arguments
142
+ end
143
+ else
144
+ inherited_arguments
145
+ end
146
+ end
147
+
148
+ def all_argument_definitions
149
+ all_defns = {}
150
+ ancestors.reverse_each do |ancestor|
151
+ if ancestor.respond_to?(:own_arguments)
152
+ all_defns.merge!(ancestor.own_arguments)
153
+ end
154
+ end
155
+ all_defns = all_defns.values
156
+ all_defns.flatten!
157
+ all_defns
158
+ end
159
+
160
+
161
+ def get_argument(argument_name, context = GraphQL::Query::NullContext)
162
+ warden = Warden.from_context(context)
163
+ for ancestor in ancestors
164
+ if ancestor.respond_to?(:own_arguments) &&
165
+ (a = ancestor.own_arguments[argument_name]) &&
166
+ (a = Warden.visible_entry?(:visible_argument?, a, context, warden))
167
+ return a
168
+ end
169
+ end
170
+ nil
113
171
  end
114
- else
115
- # might be nil if there are actually no arguments
116
- own_arguments_that_apply || own_arguments
117
172
  end
118
173
  end
119
174
 
120
- def all_argument_definitions
121
- if self.is_a?(Class)
122
- all_defns = {}
123
- ancestors.reverse_each do |ancestor|
124
- if ancestor.respond_to?(:own_arguments)
125
- all_defns.merge!(ancestor.own_arguments)
175
+ module FieldConfigured
176
+ def arguments(context = GraphQL::Query::NullContext)
177
+ own_arguments = super
178
+ if defined?(@resolver_class) && @resolver_class
179
+ inherited_arguments = @resolver_class.field_arguments(context)
180
+ if own_arguments.any?
181
+ if inherited_arguments.any?
182
+ inherited_arguments.merge(own_arguments)
183
+ else
184
+ own_arguments
185
+ end
186
+ else
187
+ inherited_arguments
126
188
  end
189
+ else
190
+ own_arguments
191
+ end
192
+ end
193
+
194
+ def all_argument_definitions
195
+ if defined?(@resolver_class) && @resolver_class
196
+ all_defns = {}
197
+ @resolver_class.all_field_argument_definitions.each do |arg_defn|
198
+ key = arg_defn.graphql_name
199
+ case (current_value = all_defns[key])
200
+ when nil
201
+ all_defns[key] = arg_defn
202
+ when Array
203
+ current_value << arg_defn
204
+ when GraphQL::Schema::Argument
205
+ all_defns[key] = [current_value, arg_defn]
206
+ else
207
+ raise "Invariant: Unexpected argument definition, #{current_value.class}: #{current_value.inspect}"
208
+ end
209
+ end
210
+ all_defns.merge!(own_arguments)
211
+ all_defns = all_defns.values
212
+ all_defns.flatten!
213
+ all_defns
214
+ else
215
+ super
127
216
  end
128
- else
129
- all_defns = own_arguments
130
217
  end
131
- all_defns = all_defns.values
218
+ end
219
+
220
+ def all_argument_definitions
221
+ all_defns = own_arguments.values
132
222
  all_defns.flatten!
133
223
  all_defns
134
224
  end
@@ -136,17 +226,11 @@ module GraphQL
136
226
  # @return [GraphQL::Schema::Argument, nil] Argument defined on this thing, fetched by name.
137
227
  def get_argument(argument_name, context = GraphQL::Query::NullContext)
138
228
  warden = Warden.from_context(context)
139
- if !self.is_a?(Class)
140
- a = own_arguments[argument_name]
141
- a && Warden.visible_entry?(:visible_argument?, a, context, warden)
229
+ if (arg_config = own_arguments[argument_name]) && (visible_arg = Warden.visible_entry?(:visible_argument?, arg_config, context, warden))
230
+ visible_arg
231
+ elsif defined?(@resolver_class) && @resolver_class
232
+ @resolver_class.get_field_argument(argument_name, context)
142
233
  else
143
- for ancestor in ancestors
144
- if ancestor.respond_to?(:own_arguments) &&
145
- (a = ancestor.own_arguments[argument_name]) &&
146
- (a = Warden.visible_entry?(:visible_argument?, a, context, warden))
147
- return a
148
- end
149
- end
150
234
  nil
151
235
  end
152
236
  end
@@ -223,7 +307,12 @@ module GraphQL
223
307
  # but not for directives.
224
308
  # TODO apply static validations on schema definitions?
225
309
  def validate_directive_argument(arg_defn, value)
226
- if arg_defn.owner.is_a?(Class) && arg_defn.owner < GraphQL::Schema::Directive
310
+ # this is only implemented on directives.
311
+ nil
312
+ end
313
+
314
+ module HasDirectiveArguments
315
+ def validate_directive_argument(arg_defn, value)
227
316
  if value.nil? && arg_defn.type.non_null?
228
317
  raise ArgumentError, "#{arg_defn.path} is required, but no value was given"
229
318
  end
@@ -281,8 +370,14 @@ module GraphQL
281
370
  end
282
371
  # Double-check that the located object is actually of this type
283
372
  # (Don't want to allow arbitrary access to objects this way)
284
- resolved_application_object_type = context.schema.resolve_type(argument.loads, application_object, context)
285
- context.schema.after_lazy(resolved_application_object_type) do |application_object_type|
373
+ maybe_lazy_resolve_type = context.schema.resolve_type(argument.loads, application_object, context)
374
+ context.schema.after_lazy(maybe_lazy_resolve_type) do |resolve_type_result|
375
+ if resolve_type_result.is_a?(Array) && resolve_type_result.size == 2
376
+ application_object_type, application_object = resolve_type_result
377
+ else
378
+ application_object_type = resolve_type_result
379
+ # application_object is already assigned
380
+ end
286
381
  possible_object_types = context.warden.possible_types(argument.loads)
287
382
  if !possible_object_types.include?(application_object_type)
288
383
  err = GraphQL::LoadApplicationObjectFailedError.new(argument: argument, id: id, object: application_object)
@@ -291,26 +386,22 @@ module GraphQL
291
386
  # This object was loaded successfully
292
387
  # and resolved to the right type,
293
388
  # now apply the `.authorized?` class method if there is one
294
- if (class_based_type = application_object_type.type_class)
295
- context.schema.after_lazy(class_based_type.authorized?(application_object, context)) do |authed|
296
- if authed
297
- application_object
389
+ context.schema.after_lazy(application_object_type.authorized?(application_object, context)) do |authed|
390
+ if authed
391
+ application_object
392
+ else
393
+ err = GraphQL::UnauthorizedError.new(
394
+ object: application_object,
395
+ type: application_object_type,
396
+ context: context,
397
+ )
398
+ if self.respond_to?(:unauthorized_object)
399
+ err.set_backtrace(caller)
400
+ unauthorized_object(err)
298
401
  else
299
- err = GraphQL::UnauthorizedError.new(
300
- object: application_object,
301
- type: class_based_type,
302
- context: context,
303
- )
304
- if self.respond_to?(:unauthorized_object)
305
- err.set_backtrace(caller)
306
- unauthorized_object(err)
307
- else
308
- raise err
309
- end
402
+ raise err
310
403
  end
311
404
  end
312
- else
313
- application_object
314
405
  end
315
406
  end
316
407
  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
@@ -11,8 +11,7 @@ module GraphQL
11
11
  # @return [void]
12
12
  def directive(dir_class, **options)
13
13
  @own_directives ||= []
14
- remove_directive(dir_class)
15
- @own_directives << dir_class.new(self, **options)
14
+ HasDirectives.add_directive(self, @own_directives, dir_class, options)
16
15
  nil
17
16
  end
18
17
 
@@ -20,78 +19,94 @@ module GraphQL
20
19
  # @param dir_class [Class<GraphQL::Schema::Directive>]
21
20
  # @return [viod]
22
21
  def remove_directive(dir_class)
23
- @own_directives && @own_directives.reject! { |d| d.is_a?(dir_class) }
22
+ HasDirectives.remove_directive(@own_directives, dir_class)
24
23
  nil
25
24
  end
26
25
 
27
26
  NO_DIRECTIVES = [].freeze
28
27
 
29
28
  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?
29
+ HasDirectives.get_directives(self, @own_directives, :directives)
30
+ end
31
+
32
+ class << self
33
+ def add_directive(schema_member, directives, directive_class, directive_options)
34
+ remove_directive(directives, directive_class) unless directive_class.repeatable?
35
+ directives << directive_class.new(schema_member, **directive_options)
36
+ end
37
+
38
+ def remove_directive(directives, directive_class)
39
+ directives && directives.reject! { |d| d.is_a?(directive_class) }
40
+ end
41
+
42
+ def get_directives(schema_member, directives, directives_method)
43
+ case schema_member
44
+ when Class
45
+ inherited_directives = if schema_member.superclass.respond_to?(directives_method)
46
+ get_directives(schema_member.superclass, schema_member.superclass.public_send(directives_method), directives_method)
47
+ else
48
+ NO_DIRECTIVES
49
+ end
50
+ if inherited_directives.any? && directives
51
+ dirs = []
52
+ merge_directives(dirs, inherited_directives)
53
+ merge_directives(dirs, directives)
54
+ dirs
55
+ elsif directives
56
+ directives
57
+ elsif inherited_directives.any?
58
+ inherited_directives
59
+ else
60
+ NO_DIRECTIVES
61
+ end
62
+ when Module
63
+ dirs = nil
64
+ schema_member.ancestors.reverse_each do |ancestor|
65
+ if ancestor.respond_to?(:own_directives) &&
66
+ (anc_dirs = ancestor.own_directives).any?
67
+ dirs ||= []
68
+ merge_directives(dirs, anc_dirs)
69
+ end
70
+ end
71
+ if directives
54
72
  dirs ||= []
55
- merge_directives(dirs, anc_dirs)
73
+ merge_directives(dirs, directives)
56
74
  end
75
+ dirs || NO_DIRECTIVES
76
+ when HasDirectives
77
+ directives || NO_DIRECTIVES
78
+ else
79
+ raise "Invariant: how could #{schema_member} not be a Class, Module, or instance of HasDirectives?"
57
80
  end
58
- if own_directives
59
- dirs ||= []
60
- merge_directives(dirs, own_directives)
81
+ end
82
+
83
+ private
84
+
85
+ # Modify `target` by adding items from `dirs` such that:
86
+ # - Any name conflict is overriden by the incoming member of `dirs`
87
+ # - Any other member of `dirs` is appended
88
+ # @param target [Array<GraphQL::Schema::Directive>]
89
+ # @param dirs [Array<GraphQL::Schema::Directive>]
90
+ # @return [void]
91
+ def merge_directives(target, dirs)
92
+ dirs.each do |dir|
93
+ if (idx = target.find_index { |d| d.graphql_name == dir.graphql_name })
94
+ target.slice!(idx)
95
+ target.insert(idx, dir)
96
+ else
97
+ target << dir
98
+ end
61
99
  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?"
100
+ nil
67
101
  end
68
102
  end
69
103
 
104
+
70
105
  protected
71
106
 
72
107
  def own_directives
73
108
  @own_directives
74
109
  end
75
-
76
- private
77
-
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
91
- end
92
- end
93
- nil
94
- end
95
110
  end
96
111
  end
97
112
  end
@@ -72,7 +72,12 @@ module GraphQL
72
72
  def add_field(field_defn, method_conflict_warning: field_defn.method_conflict_warning?)
73
73
  # Check that `field_defn.original_name` equals `resolver_method` and `method_sym` --
74
74
  # that shows that no override value was given manually.
75
- if method_conflict_warning && CONFLICT_FIELD_NAMES.include?(field_defn.resolver_method) && field_defn.original_name == field_defn.resolver_method && field_defn.original_name == field_defn.method_sym
75
+ if method_conflict_warning &&
76
+ CONFLICT_FIELD_NAMES.include?(field_defn.resolver_method) &&
77
+ field_defn.original_name == field_defn.resolver_method &&
78
+ field_defn.original_name == field_defn.method_sym &&
79
+ field_defn.hash_key == NOT_CONFIGURED &&
80
+ field_defn.dig_keys.nil?
76
81
  warn(conflict_field_name_warning(field_defn))
77
82
  end
78
83
  prev_defn = own_fields[field_defn.name]
@@ -103,10 +108,10 @@ module GraphQL
103
108
  end
104
109
 
105
110
  def global_id_field(field_name, **kwargs)
106
- id_resolver = GraphQL::Relay::GlobalIdResolve.new(type: self)
111
+ type = self
107
112
  field field_name, "ID", **kwargs, null: false
108
113
  define_method(field_name) do
109
- id_resolver.call(object, {}, context)
114
+ context.schema.id_from_object(object, type, context)
110
115
  end
111
116
  end
112
117
 
@@ -129,6 +134,13 @@ module GraphQL
129
134
 
130
135
  private
131
136
 
137
+ def inherited(subclass)
138
+ super
139
+ subclass.class_eval do
140
+ @own_fields ||= nil
141
+ end
142
+ end
143
+
132
144
  # If `type` is an interface, and `self` has a type membership for `type`, then make sure it's visible.
133
145
  def visible_interface_implementation?(type, context, warden)
134
146
  if type.respond_to?(:kind) && type.kind.interface?
@@ -23,8 +23,6 @@ module GraphQL
23
23
  int.interfaces.each do |next_interface|
24
24
  implements(next_interface)
25
25
  end
26
- elsif int.is_a?(GraphQL::InterfaceType)
27
- new_memberships << int.type_membership_class.new(int, self, **options)
28
26
  elsif int.is_a?(String) || int.is_a?(GraphQL::Schema::LateBoundType)
29
27
  if options.any?
30
28
  raise ArgumentError, "`implements(...)` doesn't support options with late-loaded types yet. Remove #{options} and open an issue to request this feature."
@@ -57,16 +55,37 @@ module GraphQL
57
55
  end
58
56
 
59
57
  def interface_type_memberships
60
- own_tms = own_interface_type_memberships
61
- if (self.is_a?(Class) && superclass.respond_to?(:interface_type_memberships))
62
- inherited_tms = superclass.interface_type_memberships
63
- if inherited_tms.size > 0
64
- own_tms + inherited_tms
65
- else
66
- own_tms
58
+ own_interface_type_memberships
59
+ end
60
+
61
+ module ClassConfigured
62
+ # This combination of extended -> inherited -> extended
63
+ # means that the base class (`Schema::Object`) *won't*
64
+ # have the superclass-related code in `InheritedInterfaces`,
65
+ # but child classes of `Schema::Object` will have it.
66
+ # That way, we don't need a `superclass.respond_to?(...)` check.
67
+ def inherited(child_class)
68
+ super
69
+ child_class.extend(InheritedInterfaces)
70
+ end
71
+
72
+ module InheritedInterfaces
73
+ def interfaces(context = GraphQL::Query::NullContext)
74
+ visible_interfaces = super
75
+ visible_interfaces.concat(superclass.interfaces(context))
76
+ visible_interfaces.uniq!
77
+ visible_interfaces
78
+ end
79
+
80
+ def interface_type_memberships
81
+ own_tms = super
82
+ inherited_tms = superclass.interface_type_memberships
83
+ if inherited_tms.size > 0
84
+ own_tms + inherited_tms
85
+ else
86
+ own_tms
87
+ end
67
88
  end
68
- else
69
- own_tms
70
89
  end
71
90
  end
72
91
 
@@ -75,25 +94,35 @@ module GraphQL
75
94
  warden = Warden.from_context(context)
76
95
  visible_interfaces = []
77
96
  own_interface_type_memberships.each do |type_membership|
78
- # During initialization, `type_memberships` can hold late-bound types
79
97
  case type_membership
80
- when String, Schema::LateBoundType
81
- visible_interfaces << type_membership
82
98
  when Schema::TypeMembership
83
99
  if warden.visible_type_membership?(type_membership, context)
84
100
  visible_interfaces << type_membership.abstract_type
85
101
  end
102
+ when String, Schema::LateBoundType
103
+ # During initialization, `type_memberships` can hold late-bound types
104
+ visible_interfaces << type_membership
86
105
  else
87
106
  raise "Invariant: Unexpected type_membership #{type_membership.class}: #{type_membership.inspect}"
88
107
  end
89
108
  end
90
-
91
- if self.is_a?(Class) && superclass <= GraphQL::Schema::Object
92
- visible_interfaces.concat(superclass.interfaces(context))
93
- end
109
+ visible_interfaces.uniq!
94
110
 
95
111
  visible_interfaces
96
112
  end
113
+
114
+ private
115
+
116
+ def self.extended(child_class)
117
+ child_class.extend(ClassConfigured)
118
+ end
119
+
120
+ def inherited(subclass)
121
+ super
122
+ subclass.class_eval do
123
+ @own_interface_type_memberships ||= nil
124
+ end
125
+ end
97
126
  end
98
127
  end
99
128
  end
@@ -18,12 +18,38 @@ module GraphQL
18
18
 
19
19
  # @return [Array<GraphQL::Schema::Validator>]
20
20
  def validators
21
- own_validators = @own_validators || EMPTY_ARRAY
22
- if self.is_a?(Class) && superclass.respond_to?(:validators) && (inherited_validators = superclass.validators).any?
23
- inherited_validators + own_validators
24
- else
25
- own_validators
21
+ @own_validators || EMPTY_ARRAY
22
+ end
23
+
24
+ module ClassConfigured
25
+ def inherited(child_cls)
26
+ super
27
+ child_cls.extend(ClassValidators)
26
28
  end
29
+
30
+ module ClassValidators
31
+ include Schema::FindInheritedValue::EmptyObjects
32
+
33
+ def validators
34
+ inherited_validators = superclass.validators
35
+ if inherited_validators.any?
36
+ if @own_validators.nil?
37
+ inherited_validators
38
+ else
39
+ inherited_validators + @own_validators
40
+ end
41
+ elsif @own_validators.nil?
42
+ EMPTY_ARRAY
43
+ else
44
+ @own_validators
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ def self.extended(child_cls)
51
+ super
52
+ child_cls.extend(ClassConfigured)
27
53
  end
28
54
  end
29
55
  end