graphql 1.9.0 → 2.1.1

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 (723) hide show
  1. checksums.yaml +5 -5
  2. data/lib/generators/graphql/core.rb +21 -9
  3. data/lib/generators/graphql/enum_generator.rb +4 -10
  4. data/lib/generators/graphql/field_extractor.rb +31 -0
  5. data/lib/generators/graphql/input_generator.rb +50 -0
  6. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  7. data/lib/generators/graphql/install/templates/base_mutation.erb +12 -0
  8. data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +4 -0
  9. data/lib/generators/graphql/install_generator.rb +49 -9
  10. data/lib/generators/graphql/interface_generator.rb +7 -7
  11. data/lib/generators/graphql/loader_generator.rb +1 -0
  12. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  13. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  14. data/lib/generators/graphql/mutation_generator.rb +6 -30
  15. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  16. data/lib/generators/graphql/object_generator.rb +28 -12
  17. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  18. data/lib/generators/graphql/relay.rb +66 -0
  19. data/lib/generators/graphql/relay_generator.rb +21 -0
  20. data/lib/generators/graphql/scalar_generator.rb +4 -2
  21. data/lib/generators/graphql/templates/base_argument.erb +8 -0
  22. data/lib/generators/graphql/templates/base_connection.erb +10 -0
  23. data/lib/generators/graphql/templates/base_edge.erb +10 -0
  24. data/lib/generators/graphql/templates/base_enum.erb +4 -0
  25. data/lib/generators/graphql/templates/base_field.erb +9 -0
  26. data/lib/generators/graphql/templates/base_input_object.erb +5 -0
  27. data/lib/generators/graphql/templates/base_interface.erb +6 -0
  28. data/lib/generators/graphql/templates/base_object.erb +5 -0
  29. data/lib/generators/graphql/templates/base_scalar.erb +4 -0
  30. data/lib/generators/graphql/templates/base_union.erb +4 -0
  31. data/lib/generators/graphql/templates/enum.erb +7 -1
  32. data/lib/generators/graphql/templates/graphql_controller.erb +23 -12
  33. data/lib/generators/graphql/templates/input.erb +9 -0
  34. data/lib/generators/graphql/templates/interface.erb +6 -2
  35. data/lib/generators/graphql/templates/loader.erb +4 -0
  36. data/lib/generators/graphql/templates/mutation.erb +5 -1
  37. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  38. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  39. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  40. data/lib/generators/graphql/templates/node_type.erb +11 -0
  41. data/lib/generators/graphql/templates/object.erb +7 -3
  42. data/lib/generators/graphql/templates/query_type.erb +5 -3
  43. data/lib/generators/graphql/templates/scalar.erb +5 -1
  44. data/lib/generators/graphql/templates/schema.erb +27 -27
  45. data/lib/generators/graphql/templates/union.erb +6 -2
  46. data/lib/generators/graphql/type_generator.rb +47 -10
  47. data/lib/generators/graphql/union_generator.rb +5 -5
  48. data/lib/graphql/analysis/ast/analyzer.rb +41 -12
  49. data/lib/graphql/analysis/ast/field_usage.rb +32 -3
  50. data/lib/graphql/analysis/ast/max_query_complexity.rb +4 -5
  51. data/lib/graphql/analysis/ast/max_query_depth.rb +7 -3
  52. data/lib/graphql/analysis/ast/query_complexity.rb +182 -66
  53. data/lib/graphql/analysis/ast/query_depth.rb +15 -26
  54. data/lib/graphql/analysis/ast/visitor.rb +83 -62
  55. data/lib/graphql/analysis/ast.rb +23 -20
  56. data/lib/graphql/analysis.rb +0 -7
  57. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  58. data/lib/graphql/backtrace/table.rb +37 -16
  59. data/lib/graphql/backtrace/trace.rb +96 -0
  60. data/lib/graphql/backtrace/traced_error.rb +0 -1
  61. data/lib/graphql/backtrace/tracer.rb +39 -9
  62. data/lib/graphql/backtrace.rb +22 -18
  63. data/lib/graphql/coercion_error.rb +8 -0
  64. data/lib/graphql/dataloader/null_dataloader.rb +24 -0
  65. data/lib/graphql/dataloader/request.rb +19 -0
  66. data/lib/graphql/dataloader/request_all.rb +19 -0
  67. data/lib/graphql/dataloader/source.rb +195 -0
  68. data/lib/graphql/dataloader.rb +320 -0
  69. data/lib/graphql/date_encoding_error.rb +16 -0
  70. data/lib/graphql/deprecation.rb +9 -0
  71. data/lib/graphql/dig.rb +1 -1
  72. data/lib/graphql/execution/directive_checks.rb +2 -2
  73. data/lib/graphql/execution/errors.rb +93 -0
  74. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  75. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  76. data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
  77. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  78. data/lib/graphql/execution/interpreter/resolve.rb +62 -24
  79. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +170 -0
  80. data/lib/graphql/execution/interpreter/runtime.rb +695 -392
  81. data/lib/graphql/execution/interpreter.rb +199 -74
  82. data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
  83. data/lib/graphql/execution/lazy.rb +11 -21
  84. data/lib/graphql/execution/lookahead.rb +110 -150
  85. data/lib/graphql/execution/multiplex.rb +6 -148
  86. data/lib/graphql/execution.rb +12 -4
  87. data/lib/graphql/execution_error.rb +3 -2
  88. data/lib/graphql/integer_decoding_error.rb +17 -0
  89. data/lib/graphql/integer_encoding_error.rb +26 -2
  90. data/lib/graphql/introspection/base_object.rb +2 -5
  91. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  92. data/lib/graphql/introspection/directive_type.rb +12 -6
  93. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  94. data/lib/graphql/introspection/entry_points.rb +6 -18
  95. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  96. data/lib/graphql/introspection/field_type.rb +9 -5
  97. data/lib/graphql/introspection/input_value_type.rb +41 -7
  98. data/lib/graphql/introspection/introspection_query.rb +6 -92
  99. data/lib/graphql/introspection/schema_type.rb +13 -12
  100. data/lib/graphql/introspection/type_type.rb +34 -17
  101. data/lib/graphql/introspection.rb +100 -0
  102. data/lib/graphql/invalid_null_error.rb +18 -0
  103. data/lib/graphql/language/block_string.rb +50 -23
  104. data/lib/graphql/language/cache.rb +37 -0
  105. data/lib/graphql/language/definition_slice.rb +21 -10
  106. data/lib/graphql/language/document_from_schema_definition.rb +153 -87
  107. data/lib/graphql/language/lexer.rb +249 -1450
  108. data/lib/graphql/language/nodes.rb +152 -142
  109. data/lib/graphql/language/parser.rb +1036 -953
  110. data/lib/graphql/language/parser.y +159 -120
  111. data/lib/graphql/language/printer.rb +342 -154
  112. data/lib/graphql/language/sanitized_printer.rb +220 -0
  113. data/lib/graphql/language/static_visitor.rb +167 -0
  114. data/lib/graphql/language/token.rb +2 -2
  115. data/lib/graphql/language/visitor.rb +196 -140
  116. data/lib/graphql/language.rb +4 -1
  117. data/lib/graphql/load_application_object_failed_error.rb +22 -0
  118. data/lib/graphql/name_validator.rb +2 -7
  119. data/lib/graphql/pagination/active_record_relation_connection.rb +77 -0
  120. data/lib/graphql/pagination/array_connection.rb +79 -0
  121. data/lib/graphql/pagination/connection.rb +275 -0
  122. data/lib/graphql/pagination/connections.rb +135 -0
  123. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  124. data/lib/graphql/pagination/relation_connection.rb +228 -0
  125. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  126. data/lib/graphql/pagination.rb +6 -0
  127. data/lib/graphql/parse_error.rb +0 -1
  128. data/lib/graphql/query/context/scoped_context.rb +101 -0
  129. data/lib/graphql/query/context.rb +157 -187
  130. data/lib/graphql/query/fingerprint.rb +26 -0
  131. data/lib/graphql/query/input_validation_result.rb +33 -7
  132. data/lib/graphql/query/null_context.rb +21 -14
  133. data/lib/graphql/query/validation_pipeline.rb +17 -38
  134. data/lib/graphql/query/variable_validation_error.rb +17 -3
  135. data/lib/graphql/query/variables.rb +49 -14
  136. data/lib/graphql/query.rb +142 -61
  137. data/lib/graphql/railtie.rb +6 -102
  138. data/lib/graphql/rake_task/validate.rb +5 -2
  139. data/lib/graphql/rake_task.rb +42 -20
  140. data/lib/graphql/relay/range_add.rb +17 -10
  141. data/lib/graphql/relay.rb +0 -15
  142. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  143. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  144. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  145. data/lib/graphql/rubocop.rb +4 -0
  146. data/lib/graphql/schema/addition.rb +271 -0
  147. data/lib/graphql/schema/always_visible.rb +10 -0
  148. data/lib/graphql/schema/argument.rb +301 -32
  149. data/lib/graphql/schema/base_64_bp.rb +3 -2
  150. data/lib/graphql/schema/base_64_encoder.rb +2 -0
  151. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
  152. data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
  153. data/lib/graphql/schema/build_from_definition.rb +349 -203
  154. data/lib/graphql/schema/built_in_types.rb +5 -5
  155. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  156. data/lib/graphql/schema/directive/feature.rb +2 -2
  157. data/lib/graphql/schema/directive/flagged.rb +57 -0
  158. data/lib/graphql/schema/directive/include.rb +2 -2
  159. data/lib/graphql/schema/directive/one_of.rb +12 -0
  160. data/lib/graphql/schema/directive/skip.rb +2 -2
  161. data/lib/graphql/schema/directive/specified_by.rb +14 -0
  162. data/lib/graphql/schema/directive/transform.rb +14 -2
  163. data/lib/graphql/schema/directive.rb +134 -15
  164. data/lib/graphql/schema/enum.rb +137 -39
  165. data/lib/graphql/schema/enum_value.rb +17 -23
  166. data/lib/graphql/schema/field/connection_extension.rb +36 -20
  167. data/lib/graphql/schema/field/scope_extension.rb +15 -5
  168. data/lib/graphql/schema/field.rb +570 -334
  169. data/lib/graphql/schema/field_extension.rb +88 -4
  170. data/lib/graphql/schema/find_inherited_value.rb +31 -0
  171. data/lib/graphql/schema/finder.rb +16 -14
  172. data/lib/graphql/schema/has_single_input_argument.rb +156 -0
  173. data/lib/graphql/schema/input_object.rb +190 -48
  174. data/lib/graphql/schema/interface.rb +24 -49
  175. data/lib/graphql/schema/introspection_system.rb +109 -36
  176. data/lib/graphql/schema/late_bound_type.rb +9 -2
  177. data/lib/graphql/schema/list.rb +61 -3
  178. data/lib/graphql/schema/loader.rb +146 -97
  179. data/lib/graphql/schema/member/base_dsl_methods.rb +45 -51
  180. data/lib/graphql/schema/member/build_type.rb +34 -17
  181. data/lib/graphql/schema/member/has_arguments.rb +385 -10
  182. data/lib/graphql/schema/member/has_ast_node.rb +32 -0
  183. data/lib/graphql/schema/member/has_deprecation_reason.rb +24 -0
  184. data/lib/graphql/schema/member/has_directives.rb +118 -0
  185. data/lib/graphql/schema/member/has_fields.rb +180 -35
  186. data/lib/graphql/schema/member/has_interfaces.rb +143 -0
  187. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  188. data/lib/graphql/schema/member/has_validators.rb +57 -0
  189. data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
  190. data/lib/graphql/schema/member/scoped.rb +19 -0
  191. data/lib/graphql/schema/member/type_system_helpers.rb +20 -3
  192. data/lib/graphql/schema/member/validates_input.rb +33 -0
  193. data/lib/graphql/schema/member.rb +11 -6
  194. data/lib/graphql/schema/mutation.rb +4 -9
  195. data/lib/graphql/schema/non_null.rb +34 -4
  196. data/lib/graphql/schema/object.rb +55 -64
  197. data/lib/graphql/schema/printer.rb +26 -40
  198. data/lib/graphql/schema/relay_classic_mutation.rb +13 -80
  199. data/lib/graphql/schema/resolver/has_payload_type.rb +53 -12
  200. data/lib/graphql/schema/resolver.rb +182 -162
  201. data/lib/graphql/schema/scalar.rb +40 -15
  202. data/lib/graphql/schema/subscription.rb +85 -27
  203. data/lib/graphql/schema/timeout.rb +119 -0
  204. data/lib/graphql/schema/type_expression.rb +21 -13
  205. data/lib/graphql/schema/type_membership.rb +51 -0
  206. data/lib/graphql/schema/union.rb +69 -15
  207. data/lib/graphql/schema/unique_within_type.rb +1 -2
  208. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  209. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  210. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  211. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  212. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  213. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  214. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  215. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  216. data/lib/graphql/schema/validator.rb +171 -0
  217. data/lib/graphql/schema/warden.rb +330 -59
  218. data/lib/graphql/schema/wrapper.rb +0 -5
  219. data/lib/graphql/schema.rb +985 -858
  220. data/lib/graphql/static_validation/all_rules.rb +4 -1
  221. data/lib/graphql/static_validation/base_visitor.rb +33 -32
  222. data/lib/graphql/static_validation/definition_dependencies.rb +28 -14
  223. data/lib/graphql/static_validation/error.rb +3 -1
  224. data/lib/graphql/static_validation/literal_validator.rb +71 -28
  225. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +46 -79
  226. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +23 -6
  227. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +35 -26
  228. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  229. data/lib/graphql/static_validation/rules/directives_are_defined.rb +12 -6
  230. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +14 -14
  231. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
  232. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +15 -7
  233. data/lib/graphql/static_validation/rules/fields_will_merge.rb +107 -57
  234. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  235. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  236. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  237. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  238. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  239. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  240. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  241. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  242. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  243. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +6 -4
  244. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +22 -10
  245. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +13 -7
  246. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
  247. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -14
  248. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  249. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
  250. data/lib/graphql/static_validation/validation_context.rb +17 -7
  251. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  252. data/lib/graphql/static_validation/validator.rb +32 -20
  253. data/lib/graphql/static_validation.rb +1 -3
  254. data/lib/graphql/string_encoding_error.rb +13 -3
  255. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +134 -24
  256. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  257. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +58 -0
  258. data/lib/graphql/subscriptions/event.rb +90 -27
  259. data/lib/graphql/subscriptions/instrumentation.rb +0 -47
  260. data/lib/graphql/subscriptions/serialize.rb +53 -6
  261. data/lib/graphql/subscriptions.rb +147 -62
  262. data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
  263. data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
  264. data/lib/graphql/tracing/appoptics_trace.rb +251 -0
  265. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  266. data/lib/graphql/tracing/appsignal_trace.rb +77 -0
  267. data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
  268. data/lib/graphql/tracing/data_dog_trace.rb +196 -0
  269. data/lib/graphql/tracing/data_dog_tracing.rb +53 -2
  270. data/lib/graphql/tracing/legacy_trace.rb +69 -0
  271. data/lib/graphql/tracing/new_relic_trace.rb +75 -0
  272. data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
  273. data/lib/graphql/tracing/notifications_trace.rb +45 -0
  274. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  275. data/lib/graphql/tracing/platform_trace.rb +118 -0
  276. data/lib/graphql/tracing/platform_tracing.rb +77 -31
  277. data/lib/graphql/tracing/prometheus_trace.rb +89 -0
  278. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +5 -2
  279. data/lib/graphql/tracing/prometheus_tracing.rb +11 -3
  280. data/lib/graphql/tracing/scout_trace.rb +72 -0
  281. data/lib/graphql/tracing/scout_tracing.rb +19 -0
  282. data/lib/graphql/tracing/statsd_trace.rb +56 -0
  283. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  284. data/lib/graphql/tracing/trace.rb +75 -0
  285. data/lib/graphql/tracing.rb +24 -67
  286. data/lib/graphql/type_kinds.rb +6 -3
  287. data/lib/graphql/types/big_int.rb +23 -0
  288. data/lib/graphql/types/int.rb +11 -3
  289. data/lib/graphql/types/iso_8601_date.rb +45 -0
  290. data/lib/graphql/types/iso_8601_date_time.rb +36 -8
  291. data/lib/graphql/types/json.rb +25 -0
  292. data/lib/graphql/types/relay/base_connection.rb +18 -90
  293. data/lib/graphql/types/relay/base_edge.rb +2 -36
  294. data/lib/graphql/types/relay/connection_behaviors.rb +193 -0
  295. data/lib/graphql/types/relay/edge_behaviors.rb +82 -0
  296. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  297. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  298. data/lib/graphql/types/relay/node.rb +2 -4
  299. data/lib/graphql/types/relay/node_behaviors.rb +25 -0
  300. data/lib/graphql/types/relay/page_info.rb +2 -14
  301. data/lib/graphql/types/relay/page_info_behaviors.rb +30 -0
  302. data/lib/graphql/types/relay.rb +10 -5
  303. data/lib/graphql/types/string.rb +8 -2
  304. data/lib/graphql/types.rb +3 -0
  305. data/lib/graphql/unauthorized_error.rb +3 -3
  306. data/lib/graphql/unauthorized_field_error.rb +1 -1
  307. data/lib/graphql/unresolved_type_error.rb +2 -2
  308. data/lib/graphql/version.rb +1 -1
  309. data/lib/graphql.rb +68 -54
  310. data/readme.md +4 -7
  311. metadata +150 -822
  312. data/lib/graphql/analysis/analyze_query.rb +0 -91
  313. data/lib/graphql/analysis/field_usage.rb +0 -45
  314. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  315. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  316. data/lib/graphql/analysis/query_complexity.rb +0 -88
  317. data/lib/graphql/analysis/query_depth.rb +0 -56
  318. data/lib/graphql/analysis/reducer_state.rb +0 -48
  319. data/lib/graphql/argument.rb +0 -153
  320. data/lib/graphql/authorization.rb +0 -82
  321. data/lib/graphql/backwards_compatibility.rb +0 -60
  322. data/lib/graphql/base_type.rb +0 -226
  323. data/lib/graphql/boolean_type.rb +0 -2
  324. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  325. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  326. data/lib/graphql/compatibility/execution_specification.rb +0 -435
  327. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  328. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -213
  329. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -91
  330. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  331. data/lib/graphql/compatibility/query_parser_specification.rb +0 -264
  332. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -680
  333. data/lib/graphql/compatibility.rb +0 -5
  334. data/lib/graphql/define/assign_argument.rb +0 -12
  335. data/lib/graphql/define/assign_connection.rb +0 -13
  336. data/lib/graphql/define/assign_enum_value.rb +0 -18
  337. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  338. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  339. data/lib/graphql/define/assign_object_field.rb +0 -42
  340. data/lib/graphql/define/defined_object_proxy.rb +0 -50
  341. data/lib/graphql/define/instance_definable.rb +0 -300
  342. data/lib/graphql/define/no_definition_error.rb +0 -7
  343. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  344. data/lib/graphql/define/type_definer.rb +0 -31
  345. data/lib/graphql/define.rb +0 -31
  346. data/lib/graphql/deprecated_dsl.rb +0 -42
  347. data/lib/graphql/directive/deprecated_directive.rb +0 -13
  348. data/lib/graphql/directive/include_directive.rb +0 -2
  349. data/lib/graphql/directive/skip_directive.rb +0 -2
  350. data/lib/graphql/directive.rb +0 -104
  351. data/lib/graphql/enum_type.rb +0 -193
  352. data/lib/graphql/execution/execute.rb +0 -319
  353. data/lib/graphql/execution/flatten.rb +0 -40
  354. data/lib/graphql/execution/instrumentation.rb +0 -92
  355. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  356. data/lib/graphql/execution/lazy/resolve.rb +0 -91
  357. data/lib/graphql/execution/typecast.rb +0 -50
  358. data/lib/graphql/field/resolve.rb +0 -59
  359. data/lib/graphql/field.rb +0 -330
  360. data/lib/graphql/filter.rb +0 -53
  361. data/lib/graphql/float_type.rb +0 -2
  362. data/lib/graphql/function.rb +0 -153
  363. data/lib/graphql/id_type.rb +0 -2
  364. data/lib/graphql/input_object_type.rb +0 -153
  365. data/lib/graphql/int_type.rb +0 -2
  366. data/lib/graphql/interface_type.rb +0 -86
  367. data/lib/graphql/internal_representation/document.rb +0 -27
  368. data/lib/graphql/internal_representation/node.rb +0 -206
  369. data/lib/graphql/internal_representation/print.rb +0 -51
  370. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  371. data/lib/graphql/internal_representation/scope.rb +0 -88
  372. data/lib/graphql/internal_representation/visit.rb +0 -36
  373. data/lib/graphql/internal_representation.rb +0 -7
  374. data/lib/graphql/language/lexer.rl +0 -236
  375. data/lib/graphql/list_type.rb +0 -80
  376. data/lib/graphql/literal_validation_error.rb +0 -6
  377. data/lib/graphql/non_null_type.rb +0 -81
  378. data/lib/graphql/object_type.rb +0 -141
  379. data/lib/graphql/query/arguments.rb +0 -179
  380. data/lib/graphql/query/arguments_cache.rb +0 -25
  381. data/lib/graphql/query/executor.rb +0 -53
  382. data/lib/graphql/query/literal_input.rb +0 -115
  383. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  384. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  385. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  386. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  387. data/lib/graphql/query/serial_execution.rb +0 -39
  388. data/lib/graphql/relay/array_connection.rb +0 -85
  389. data/lib/graphql/relay/base_connection.rb +0 -172
  390. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  391. data/lib/graphql/relay/connection_resolve.rb +0 -43
  392. data/lib/graphql/relay/connection_type.rb +0 -40
  393. data/lib/graphql/relay/edge.rb +0 -27
  394. data/lib/graphql/relay/edge_type.rb +0 -18
  395. data/lib/graphql/relay/edges_instrumentation.rb +0 -40
  396. data/lib/graphql/relay/global_id_resolve.rb +0 -18
  397. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  398. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  399. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  400. data/lib/graphql/relay/mutation/result.rb +0 -38
  401. data/lib/graphql/relay/mutation.rb +0 -190
  402. data/lib/graphql/relay/node.rb +0 -36
  403. data/lib/graphql/relay/page_info.rb +0 -7
  404. data/lib/graphql/relay/relation_connection.rb +0 -186
  405. data/lib/graphql/relay/type_extensions.rb +0 -30
  406. data/lib/graphql/scalar_type.rb +0 -135
  407. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  408. data/lib/graphql/schema/default_parse_error.rb +0 -10
  409. data/lib/graphql/schema/default_type_error.rb +0 -15
  410. data/lib/graphql/schema/member/accepts_definition.rb +0 -152
  411. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -26
  412. data/lib/graphql/schema/member/instrumentation.rb +0 -121
  413. data/lib/graphql/schema/middleware_chain.rb +0 -82
  414. data/lib/graphql/schema/possible_types.rb +0 -39
  415. data/lib/graphql/schema/rescue_middleware.rb +0 -55
  416. data/lib/graphql/schema/timeout_middleware.rb +0 -85
  417. data/lib/graphql/schema/traversal.rb +0 -228
  418. data/lib/graphql/schema/validation.rb +0 -286
  419. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  420. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  421. data/lib/graphql/static_validation/type_stack.rb +0 -216
  422. data/lib/graphql/string_type.rb +0 -2
  423. data/lib/graphql/subscriptions/subscription_root.rb +0 -66
  424. data/lib/graphql/tracing/skylight_tracing.rb +0 -61
  425. data/lib/graphql/types/relay/base_field.rb +0 -22
  426. data/lib/graphql/types/relay/base_interface.rb +0 -29
  427. data/lib/graphql/types/relay/base_object.rb +0 -26
  428. data/lib/graphql/types/relay/node_field.rb +0 -43
  429. data/lib/graphql/types/relay/nodes_field.rb +0 -45
  430. data/lib/graphql/union_type.rb +0 -100
  431. data/lib/graphql/upgrader/member.rb +0 -899
  432. data/lib/graphql/upgrader/schema.rb +0 -37
  433. data/spec/dummy/Gemfile +0 -12
  434. data/spec/dummy/Gemfile.lock +0 -157
  435. data/spec/dummy/README.md +0 -24
  436. data/spec/dummy/Rakefile +0 -7
  437. data/spec/dummy/app/assets/config/manifest.js +0 -1
  438. data/spec/dummy/app/assets/javascripts/application.js +0 -66
  439. data/spec/dummy/app/channels/application_cable/channel.rb +0 -5
  440. data/spec/dummy/app/channels/application_cable/connection.rb +0 -5
  441. data/spec/dummy/app/channels/graphql_channel.rb +0 -116
  442. data/spec/dummy/app/controllers/application_controller.rb +0 -4
  443. data/spec/dummy/app/controllers/pages_controller.rb +0 -5
  444. data/spec/dummy/app/helpers/application_helper.rb +0 -3
  445. data/spec/dummy/app/jobs/application_job.rb +0 -3
  446. data/spec/dummy/app/views/layouts/application.html.erb +0 -12
  447. data/spec/dummy/app/views/pages/show.html +0 -16
  448. data/spec/dummy/bin/bundle +0 -4
  449. data/spec/dummy/bin/rails +0 -5
  450. data/spec/dummy/bin/rake +0 -5
  451. data/spec/dummy/bin/setup +0 -31
  452. data/spec/dummy/bin/update +0 -27
  453. data/spec/dummy/bin/yarn +0 -12
  454. data/spec/dummy/config/application.rb +0 -30
  455. data/spec/dummy/config/boot.rb +0 -4
  456. data/spec/dummy/config/cable.yml +0 -10
  457. data/spec/dummy/config/environment.rb +0 -6
  458. data/spec/dummy/config/environments/development.rb +0 -40
  459. data/spec/dummy/config/environments/production.rb +0 -76
  460. data/spec/dummy/config/environments/test.rb +0 -37
  461. data/spec/dummy/config/initializers/application_controller_renderer.rb +0 -9
  462. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -8
  463. data/spec/dummy/config/initializers/cookies_serializer.rb +0 -6
  464. data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -5
  465. data/spec/dummy/config/initializers/inflections.rb +0 -17
  466. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  467. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -10
  468. data/spec/dummy/config/locales/en.yml +0 -33
  469. data/spec/dummy/config/puma.rb +0 -57
  470. data/spec/dummy/config/routes.rb +0 -4
  471. data/spec/dummy/config/secrets.yml +0 -32
  472. data/spec/dummy/config.ru +0 -6
  473. data/spec/dummy/log/test.log +0 -199
  474. data/spec/dummy/package.json +0 -5
  475. data/spec/dummy/public/404.html +0 -67
  476. data/spec/dummy/public/422.html +0 -67
  477. data/spec/dummy/public/500.html +0 -66
  478. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  479. data/spec/dummy/public/apple-touch-icon.png +0 -0
  480. data/spec/dummy/public/favicon.ico +0 -0
  481. data/spec/dummy/public/robots.txt +0 -1
  482. data/spec/dummy/test/application_system_test_case.rb +0 -6
  483. data/spec/dummy/test/system/action_cable_subscription_test.rb +0 -45
  484. data/spec/dummy/test/test_helper.rb +0 -4
  485. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4w/4wzXRZrAkwKdgYaSE0pid5eB-fer8vSfSku_NPg4rMA.cache +0 -0
  486. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7I/7IHVBiJT06QSpgLpLoJIxboQ0B-D_tMTxsvoezBTV3Q.cache +0 -1
  487. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8w/8wY_SKagj8wHuwGNAAf6JnQ8joMbC6cEYpHrTAI8Urc.cache +0 -1
  488. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/AK/AKzz1u6bGb4auXcrObA_g5LL-oV0ejNGa448AgAi_WQ.cache +0 -1
  489. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ET/ETW4uxvaYpruL8y6_ZptUH82ZowMaHIqvg5WexBFdEM.cache +0 -3
  490. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F1/F1TWpjjyA56k9Z90n5B3xRn7DUdGjX73QCkYC6k07JQ.cache +0 -0
  491. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -2
  492. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -2
  493. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ms/MsKSimH_UCB-H1tLvDABDHuvGciuoW6kVqQWDrXU5FQ.cache +0 -0
  494. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Mt/Mtci-Kim50aPOmeClD4AIicKn1d1WJ0n454IjSd94sk.cache +0 -0
  495. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QH/QHt3Tc1Y6M66Oo_pDuMyWrQNs4Pp3SMeZR5K1wJj2Ts.cache +0 -1
  496. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/XU/XU4k1OXnfMils5SrirorPvDSyDSqiOWLZNtmAH1HH8k.cache +0 -0
  497. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ZI/ZIof7mZxWWCnraIFOCuV6a8QRWzKJXJnx2Xd7C0ZyX0.cache +0 -1
  498. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cG/cGc_puuPS5pZKgUcy1Y_i1L6jl5UtsiIrMH59rTzR6c.cache +0 -3
  499. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/df/dfro_B6bx3KP1Go-7jEOqqZ2j4hVRseXIc3es9PKQno.cache +0 -1
  500. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jO/jO1DfbqnG0mTULsjJJANc3fefrG2zt7DIMmcptMT628.cache +0 -1
  501. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pE/pE7gO6pQ-z187Swb4hT554wmqsq-cNzgPWLrCz-LQQQ.cache +0 -0
  502. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/r9/r9iU1l58a6rxkZSW5RSC52_tD-_UQuHxoMVnkfJ7Mhs.cache +0 -1
  503. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xi/xitPPFfPIyDMpaznV0sBBcw8eSCV8PJcLLWin78sCgE.cache +0 -0
  504. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  505. data/spec/fixtures/upgrader/account.original.rb +0 -19
  506. data/spec/fixtures/upgrader/account.transformed.rb +0 -20
  507. data/spec/fixtures/upgrader/blame_range.original.rb +0 -43
  508. data/spec/fixtures/upgrader/blame_range.transformed.rb +0 -30
  509. data/spec/fixtures/upgrader/date_time.original.rb +0 -24
  510. data/spec/fixtures/upgrader/date_time.transformed.rb +0 -23
  511. data/spec/fixtures/upgrader/delete_project.original.rb +0 -28
  512. data/spec/fixtures/upgrader/delete_project.transformed.rb +0 -27
  513. data/spec/fixtures/upgrader/gist_order_field.original.rb +0 -14
  514. data/spec/fixtures/upgrader/gist_order_field.transformed.rb +0 -13
  515. data/spec/fixtures/upgrader/increment_count.original.rb +0 -59
  516. data/spec/fixtures/upgrader/increment_count.transformed.rb +0 -50
  517. data/spec/fixtures/upgrader/photo.original.rb +0 -10
  518. data/spec/fixtures/upgrader/photo.transformed.rb +0 -12
  519. data/spec/fixtures/upgrader/release_order.original.rb +0 -15
  520. data/spec/fixtures/upgrader/release_order.transformed.rb +0 -14
  521. data/spec/fixtures/upgrader/starrable.original.rb +0 -49
  522. data/spec/fixtures/upgrader/starrable.transformed.rb +0 -46
  523. data/spec/fixtures/upgrader/subscribable.original.rb +0 -55
  524. data/spec/fixtures/upgrader/subscribable.transformed.rb +0 -51
  525. data/spec/fixtures/upgrader/type_x.original.rb +0 -65
  526. data/spec/fixtures/upgrader/type_x.transformed.rb +0 -56
  527. data/spec/graphql/analysis/analyze_query_spec.rb +0 -272
  528. data/spec/graphql/analysis/ast/field_usage_spec.rb +0 -51
  529. data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +0 -120
  530. data/spec/graphql/analysis/ast/max_query_depth_spec.rb +0 -114
  531. data/spec/graphql/analysis/ast/query_complexity_spec.rb +0 -299
  532. data/spec/graphql/analysis/ast/query_depth_spec.rb +0 -108
  533. data/spec/graphql/analysis/ast_spec.rb +0 -269
  534. data/spec/graphql/analysis/field_usage_spec.rb +0 -62
  535. data/spec/graphql/analysis/max_query_complexity_spec.rb +0 -102
  536. data/spec/graphql/analysis/max_query_depth_spec.rb +0 -101
  537. data/spec/graphql/analysis/query_complexity_spec.rb +0 -301
  538. data/spec/graphql/analysis/query_depth_spec.rb +0 -81
  539. data/spec/graphql/argument_spec.rb +0 -159
  540. data/spec/graphql/authorization_spec.rb +0 -901
  541. data/spec/graphql/backtrace_spec.rb +0 -206
  542. data/spec/graphql/base_type_spec.rb +0 -171
  543. data/spec/graphql/boolean_type_spec.rb +0 -21
  544. data/spec/graphql/compatibility/execution_specification_spec.rb +0 -4
  545. data/spec/graphql/compatibility/lazy_execution_specification_spec.rb +0 -4
  546. data/spec/graphql/compatibility/query_parser_specification_spec.rb +0 -6
  547. data/spec/graphql/compatibility/schema_parser_specification_spec.rb +0 -6
  548. data/spec/graphql/define/assign_argument_spec.rb +0 -61
  549. data/spec/graphql/define/instance_definable_spec.rb +0 -203
  550. data/spec/graphql/directive/skip_directive_spec.rb +0 -9
  551. data/spec/graphql/directive_spec.rb +0 -295
  552. data/spec/graphql/enum_type_spec.rb +0 -158
  553. data/spec/graphql/execution/execute_spec.rb +0 -303
  554. data/spec/graphql/execution/instrumentation_spec.rb +0 -184
  555. data/spec/graphql/execution/interpreter_spec.rb +0 -485
  556. data/spec/graphql/execution/lazy/lazy_method_map_spec.rb +0 -57
  557. data/spec/graphql/execution/lazy_spec.rb +0 -240
  558. data/spec/graphql/execution/lookahead_spec.rb +0 -363
  559. data/spec/graphql/execution/multiplex_spec.rb +0 -211
  560. data/spec/graphql/execution/typecast_spec.rb +0 -47
  561. data/spec/graphql/execution_error_spec.rb +0 -325
  562. data/spec/graphql/field_spec.rb +0 -246
  563. data/spec/graphql/float_type_spec.rb +0 -16
  564. data/spec/graphql/function_spec.rb +0 -129
  565. data/spec/graphql/id_type_spec.rb +0 -33
  566. data/spec/graphql/input_object_type_spec.rb +0 -25
  567. data/spec/graphql/int_type_spec.rb +0 -35
  568. data/spec/graphql/interface_type_spec.rb +0 -196
  569. data/spec/graphql/internal_representation/print_spec.rb +0 -41
  570. data/spec/graphql/internal_representation/rewrite_spec.rb +0 -376
  571. data/spec/graphql/introspection/directive_type_spec.rb +0 -61
  572. data/spec/graphql/introspection/input_value_type_spec.rb +0 -105
  573. data/spec/graphql/introspection/introspection_query_spec.rb +0 -59
  574. data/spec/graphql/introspection/schema_type_spec.rb +0 -56
  575. data/spec/graphql/introspection/type_type_spec.rb +0 -155
  576. data/spec/graphql/language/block_string_spec.rb +0 -70
  577. data/spec/graphql/language/definition_slice_spec.rb +0 -226
  578. data/spec/graphql/language/document_from_schema_definition_spec.rb +0 -770
  579. data/spec/graphql/language/equality_spec.rb +0 -84
  580. data/spec/graphql/language/generation_spec.rb +0 -38
  581. data/spec/graphql/language/lexer_spec.rb +0 -135
  582. data/spec/graphql/language/nodes_spec.rb +0 -67
  583. data/spec/graphql/language/parser_spec.rb +0 -175
  584. data/spec/graphql/language/printer_spec.rb +0 -215
  585. data/spec/graphql/language/visitor_spec.rb +0 -400
  586. data/spec/graphql/list_type_spec.rb +0 -57
  587. data/spec/graphql/non_null_type_spec.rb +0 -48
  588. data/spec/graphql/object_type_spec.rb +0 -197
  589. data/spec/graphql/query/arguments_spec.rb +0 -346
  590. data/spec/graphql/query/context_spec.rb +0 -292
  591. data/spec/graphql/query/executor_spec.rb +0 -314
  592. data/spec/graphql/query/literal_input_spec.rb +0 -91
  593. data/spec/graphql/query/result_spec.rb +0 -29
  594. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +0 -109
  595. data/spec/graphql/query_spec.rb +0 -800
  596. data/spec/graphql/rake_task_spec.rb +0 -59
  597. data/spec/graphql/scalar_type_spec.rb +0 -66
  598. data/spec/graphql/schema/argument_spec.rb +0 -127
  599. data/spec/graphql/schema/build_from_definition_spec.rb +0 -1187
  600. data/spec/graphql/schema/catchall_middleware_spec.rb +0 -35
  601. data/spec/graphql/schema/directive/feature_spec.rb +0 -81
  602. data/spec/graphql/schema/directive/transform_spec.rb +0 -39
  603. data/spec/graphql/schema/enum_spec.rb +0 -83
  604. data/spec/graphql/schema/enum_value_spec.rb +0 -24
  605. data/spec/graphql/schema/field_extension_spec.rb +0 -115
  606. data/spec/graphql/schema/field_spec.rb +0 -301
  607. data/spec/graphql/schema/finder_spec.rb +0 -135
  608. data/spec/graphql/schema/input_object_spec.rb +0 -238
  609. data/spec/graphql/schema/instrumentation_spec.rb +0 -43
  610. data/spec/graphql/schema/interface_spec.rb +0 -215
  611. data/spec/graphql/schema/introspection_system_spec.rb +0 -47
  612. data/spec/graphql/schema/list_spec.rb +0 -46
  613. data/spec/graphql/schema/loader_spec.rb +0 -286
  614. data/spec/graphql/schema/member/accepts_definition_spec.rb +0 -115
  615. data/spec/graphql/schema/member/build_type_spec.rb +0 -63
  616. data/spec/graphql/schema/member/scoped_spec.rb +0 -177
  617. data/spec/graphql/schema/member/type_system_helpers_spec.rb +0 -63
  618. data/spec/graphql/schema/middleware_chain_spec.rb +0 -57
  619. data/spec/graphql/schema/mutation_spec.rb +0 -150
  620. data/spec/graphql/schema/non_null_spec.rb +0 -46
  621. data/spec/graphql/schema/object_spec.rb +0 -244
  622. data/spec/graphql/schema/printer_spec.rb +0 -869
  623. data/spec/graphql/schema/relay_classic_mutation_spec.rb +0 -234
  624. data/spec/graphql/schema/rescue_middleware_spec.rb +0 -74
  625. data/spec/graphql/schema/resolver_spec.rb +0 -640
  626. data/spec/graphql/schema/scalar_spec.rb +0 -101
  627. data/spec/graphql/schema/subscription_spec.rb +0 -416
  628. data/spec/graphql/schema/timeout_middleware_spec.rb +0 -188
  629. data/spec/graphql/schema/traversal_spec.rb +0 -222
  630. data/spec/graphql/schema/type_expression_spec.rb +0 -39
  631. data/spec/graphql/schema/union_spec.rb +0 -72
  632. data/spec/graphql/schema/unique_within_type_spec.rb +0 -44
  633. data/spec/graphql/schema/validation_spec.rb +0 -355
  634. data/spec/graphql/schema/warden_spec.rb +0 -926
  635. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +0 -413
  636. data/spec/graphql/static_validation/rules/argument_names_are_unique_spec.rb +0 -44
  637. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +0 -112
  638. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +0 -35
  639. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +0 -42
  640. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +0 -167
  641. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +0 -66
  642. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +0 -740
  643. data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +0 -28
  644. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +0 -52
  645. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +0 -42
  646. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +0 -123
  647. data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +0 -24
  648. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +0 -56
  649. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +0 -61
  650. data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +0 -39
  651. data/spec/graphql/static_validation/rules/no_definitions_are_present_spec.rb +0 -62
  652. data/spec/graphql/static_validation/rules/operation_names_are_valid_spec.rb +0 -82
  653. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +0 -73
  654. data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb +0 -58
  655. data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +0 -34
  656. data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +0 -188
  657. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +0 -196
  658. data/spec/graphql/static_validation/rules/variable_names_are_unique_spec.rb +0 -23
  659. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +0 -236
  660. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +0 -78
  661. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +0 -81
  662. data/spec/graphql/static_validation/type_stack_spec.rb +0 -29
  663. data/spec/graphql/static_validation/validator_spec.rb +0 -204
  664. data/spec/graphql/string_type_spec.rb +0 -80
  665. data/spec/graphql/subscriptions/serialize_spec.rb +0 -49
  666. data/spec/graphql/subscriptions_spec.rb +0 -502
  667. data/spec/graphql/tracing/new_relic_tracing_spec.rb +0 -63
  668. data/spec/graphql/tracing/platform_tracing_spec.rb +0 -137
  669. data/spec/graphql/tracing/prometheus_tracing_spec.rb +0 -42
  670. data/spec/graphql/tracing/scout_tracing_spec.rb +0 -17
  671. data/spec/graphql/tracing/skylight_tracing_spec.rb +0 -63
  672. data/spec/graphql/tracing_spec.rb +0 -52
  673. data/spec/graphql/types/iso_8601_date_time_spec.rb +0 -137
  674. data/spec/graphql/union_type_spec.rb +0 -211
  675. data/spec/graphql/upgrader/member_spec.rb +0 -583
  676. data/spec/graphql/upgrader/schema_spec.rb +0 -82
  677. data/spec/integration/mongoid/graphql/relay/mongo_relation_connection_spec.rb +0 -528
  678. data/spec/integration/mongoid/spec_helper.rb +0 -2
  679. data/spec/integration/mongoid/star_trek/data.rb +0 -126
  680. data/spec/integration/mongoid/star_trek/schema.rb +0 -425
  681. data/spec/integration/rails/data.rb +0 -110
  682. data/spec/integration/rails/generators/base_generator_test.rb +0 -7
  683. data/spec/integration/rails/generators/graphql/enum_generator_spec.rb +0 -30
  684. data/spec/integration/rails/generators/graphql/install_generator_spec.rb +0 -218
  685. data/spec/integration/rails/generators/graphql/interface_generator_spec.rb +0 -34
  686. data/spec/integration/rails/generators/graphql/loader_generator_spec.rb +0 -59
  687. data/spec/integration/rails/generators/graphql/mutation_generator_spec.rb +0 -71
  688. data/spec/integration/rails/generators/graphql/object_generator_spec.rb +0 -54
  689. data/spec/integration/rails/generators/graphql/scalar_generator_spec.rb +0 -28
  690. data/spec/integration/rails/generators/graphql/union_generator_spec.rb +0 -67
  691. data/spec/integration/rails/graphql/input_object_type_spec.rb +0 -364
  692. data/spec/integration/rails/graphql/query/variables_spec.rb +0 -375
  693. data/spec/integration/rails/graphql/relay/array_connection_spec.rb +0 -290
  694. data/spec/integration/rails/graphql/relay/base_connection_spec.rb +0 -101
  695. data/spec/integration/rails/graphql/relay/connection_instrumentation_spec.rb +0 -80
  696. data/spec/integration/rails/graphql/relay/connection_resolve_spec.rb +0 -79
  697. data/spec/integration/rails/graphql/relay/connection_type_spec.rb +0 -106
  698. data/spec/integration/rails/graphql/relay/edge_spec.rb +0 -10
  699. data/spec/integration/rails/graphql/relay/mutation_spec.rb +0 -387
  700. data/spec/integration/rails/graphql/relay/node_spec.rb +0 -263
  701. data/spec/integration/rails/graphql/relay/page_info_spec.rb +0 -111
  702. data/spec/integration/rails/graphql/relay/range_add_spec.rb +0 -117
  703. data/spec/integration/rails/graphql/relay/relation_connection_spec.rb +0 -837
  704. data/spec/integration/rails/graphql/schema_spec.rb +0 -476
  705. data/spec/integration/rails/graphql/tracing/active_support_notifications_tracing_spec.rb +0 -62
  706. data/spec/integration/rails/spec_helper.rb +0 -25
  707. data/spec/integration/tmp/app/graphql/types/family_type.rb +0 -9
  708. data/spec/spec_helper.rb +0 -116
  709. data/spec/support/dummy/data.rb +0 -45
  710. data/spec/support/dummy/schema.rb +0 -492
  711. data/spec/support/error_bubbling_helpers.rb +0 -23
  712. data/spec/support/global_id.rb +0 -23
  713. data/spec/support/jazz.rb +0 -759
  714. data/spec/support/lazy_helpers.rb +0 -192
  715. data/spec/support/magic_cards/schema.graphql +0 -33
  716. data/spec/support/minimum_input_object.rb +0 -21
  717. data/spec/support/new_relic.rb +0 -27
  718. data/spec/support/parser/filename_example.graphql +0 -5
  719. data/spec/support/parser/filename_example_error_1.graphql +0 -4
  720. data/spec/support/parser/filename_example_error_2.graphql +0 -5
  721. data/spec/support/skylight.rb +0 -39
  722. data/spec/support/star_wars/schema.rb +0 -465
  723. data/spec/support/static_validation_helpers.rb +0 -32
@@ -1,15 +1,21 @@
1
1
  # frozen_string_literal: true
2
- # test_via: ../object.rb
3
2
  require "graphql/schema/field/connection_extension"
4
3
  require "graphql/schema/field/scope_extension"
5
4
 
6
5
  module GraphQL
7
6
  class Schema
8
7
  class Field
9
- include GraphQL::Schema::Member::CachedGraphQLDefinition
10
- include GraphQL::Schema::Member::AcceptsDefinition
11
8
  include GraphQL::Schema::Member::HasArguments
9
+ include GraphQL::Schema::Member::HasArguments::FieldConfigured
10
+ include GraphQL::Schema::Member::HasAstNode
12
11
  include GraphQL::Schema::Member::HasPath
12
+ include GraphQL::Schema::Member::HasValidators
13
+ extend GraphQL::Schema::FindInheritedValue
14
+ include GraphQL::EmptyObjects
15
+ include GraphQL::Schema::Member::HasDirectives
16
+ include GraphQL::Schema::Member::HasDeprecationReason
17
+
18
+ class FieldImplementationFailed < GraphQL::Error; end
13
19
 
14
20
  # @return [String] the GraphQL name for this field, camelized unless `camelize: false` is provided
15
21
  attr_reader :name
@@ -17,22 +23,39 @@ module GraphQL
17
23
 
18
24
  attr_writer :description
19
25
 
20
- # @return [String, nil] If present, the field is marked as deprecated with this documentation
21
- attr_accessor :deprecation_reason
22
-
23
26
  # @return [Symbol] Method or hash key on the underlying object to look up
24
27
  attr_reader :method_sym
25
28
 
26
29
  # @return [String] Method or hash key on the underlying object to look up
27
30
  attr_reader :method_str
28
31
 
32
+ attr_reader :hash_key
33
+ attr_reader :dig_keys
34
+
29
35
  # @return [Symbol] The method on the type to look up
30
- attr_reader :resolver_method
36
+ def resolver_method
37
+ if @resolver_class
38
+ @resolver_class.resolver_method
39
+ else
40
+ @resolver_method
41
+ end
42
+ end
31
43
 
32
- # @return [Class] The type that this field belongs to
33
- attr_reader :owner
44
+ # @return [Class] The thing this field was defined on (type, mutation, resolver)
45
+ attr_accessor :owner
34
46
 
35
- # @return [Symobol] the original name of the field, passed in by the user
47
+ # @return [Class] The GraphQL type this field belongs to. (For fields defined on mutations, it's the payload type)
48
+ def owner_type
49
+ @owner_type ||= if owner.nil?
50
+ raise GraphQL::InvariantError, "Field #{original_name.inspect} (graphql name: #{graphql_name.inspect}) has no owner, but all fields should have an owner. How did this happen?!"
51
+ elsif owner < GraphQL::Schema::Mutation
52
+ owner.payload_type
53
+ else
54
+ owner
55
+ end
56
+ end
57
+
58
+ # @return [Symbol] the original name of the field, passed in by the user
36
59
  attr_reader :original_name
37
60
 
38
61
  # @return [Class, nil] The {Schema::Resolver} this field was derived from, if there is one
@@ -40,16 +63,25 @@ module GraphQL
40
63
  @resolver_class
41
64
  end
42
65
 
43
- alias :mutation :resolver
66
+ # @return [Boolean] Is this field a predefined introspection field?
67
+ def introspection?
68
+ @introspection
69
+ end
44
70
 
45
- # @return [Array<Symbol>]
46
- attr_reader :extras
71
+ def inspect
72
+ "#<#{self.class} #{path}#{all_argument_definitions.any? ? "(...)" : ""}: #{type.to_type_signature}>"
73
+ end
74
+
75
+ alias :mutation :resolver
47
76
 
48
77
  # @return [Boolean] Apply tracing to this field? (Default: skip scalars, this is the override value)
49
78
  attr_reader :trace
50
79
 
51
80
  # @return [String, nil]
52
- attr_reader :subscription_scope
81
+ def subscription_scope
82
+ @subscription_scope || (@resolver_class.respond_to?(:subscription_scope) ? @resolver_class.subscription_scope : nil)
83
+ end
84
+ attr_writer :subscription_scope
53
85
 
54
86
  # Create a field instance from a list of arguments, keyword arguments, and a block.
55
87
  #
@@ -60,24 +92,12 @@ module GraphQL
60
92
  # @param resolver [Class] A {GraphQL::Schema::Resolver} class to use for field configuration
61
93
  # @param mutation [Class] A {GraphQL::Schema::Mutation} class to use for field configuration
62
94
  # @param subscription [Class] A {GraphQL::Schema::Subscription} class to use for field configuration
63
- # @return [GraphQL::Schema:Field] an instance of `self
95
+ # @return [GraphQL::Schema:Field] an instance of `self`
64
96
  # @see {.initialize} for other options
65
97
  def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
66
- if kwargs[:field]
67
- if kwargs[:field] == GraphQL::Relay::Node.field
68
- warn("Legacy-style `GraphQL::Relay::Node.field` is being added to a class-based type. See `GraphQL::Types::Relay::NodeField` for a replacement.")
69
- return GraphQL::Types::Relay::NodeField
70
- elsif kwargs[:field] == GraphQL::Relay::Node.plural_field
71
- warn("Legacy-style `GraphQL::Relay::Node.plural_field` is being added to a class-based type. See `GraphQL::Types::Relay::NodesField` for a replacement.")
72
- return GraphQL::Types::Relay::NodesField
73
- end
74
- end
75
-
76
- if (parent_config = resolver || mutation || subscription)
77
- # Get the parent config, merge in local overrides
78
- kwargs = parent_config.field_options.merge(kwargs)
98
+ if (resolver_class = resolver || mutation || subscription)
79
99
  # Add a reference to that parent class
80
- kwargs[:resolver_class] = parent_config
100
+ kwargs[:resolver_class] = resolver_class
81
101
  end
82
102
 
83
103
  if name
@@ -85,9 +105,6 @@ module GraphQL
85
105
  end
86
106
 
87
107
  if !type.nil?
88
- if type.is_a?(GraphQL::Field)
89
- raise ArgumentError, "A GraphQL::Field was passed as the second argument, use the `field:` keyword for this instead."
90
- end
91
108
  if desc
92
109
  if kwargs[:description]
93
110
  raise ArgumentError, "Provide description as a positional argument or `description:` keyword, but not both (#{desc.inspect}, #{kwargs[:description].inspect})"
@@ -95,12 +112,15 @@ module GraphQL
95
112
 
96
113
  kwargs[:description] = desc
97
114
  kwargs[:type] = type
98
- elsif (kwargs[:field] || kwargs[:function] || resolver || mutation) && type.is_a?(String)
99
- # The return type should be copied from `field` or `function`, and the second positional argument is the description
115
+ elsif (resolver || mutation) && type.is_a?(String)
116
+ # The return type should be copied from the resolver, and the second positional argument is the description
100
117
  kwargs[:description] = type
101
118
  else
102
119
  kwargs[:type] = type
103
120
  end
121
+ if type.is_a?(Class) && type < GraphQL::Schema::Mutation
122
+ raise ArgumentError, "Use `field #{name.inspect}, mutation: Mutation, ...` to provide a mutation to this field instead"
123
+ end
104
124
  end
105
125
  new(**kwargs, &block)
106
126
  end
@@ -110,10 +130,10 @@ module GraphQL
110
130
  def connection?
111
131
  if @connection.nil?
112
132
  # Provide default based on type name
113
- return_type_name = if (contains_type = @field || @function)
114
- Member::BuildType.to_type_name(contains_type.type)
115
- elsif @return_type_expr
133
+ return_type_name = if @return_type_expr
116
134
  Member::BuildType.to_type_name(@return_type_expr)
135
+ elsif @resolver_class && @resolver_class.type
136
+ Member::BuildType.to_type_name(@resolver_class.type)
117
137
  else
118
138
  # As a last ditch, try to force loading the return type:
119
139
  type.unwrap.name
@@ -129,64 +149,98 @@ module GraphQL
129
149
  if !@scope.nil?
130
150
  # The default was overridden
131
151
  @scope
152
+ elsif @return_type_expr
153
+ # Detect a list return type, but don't call `type` since that may eager-load an otherwise lazy-loaded type
154
+ @return_type_expr.is_a?(Array) ||
155
+ (@return_type_expr.is_a?(String) && @return_type_expr.include?("[")) ||
156
+ connection?
157
+ elsif @resolver_class
158
+ resolver_type = @resolver_class.type_expr
159
+ resolver_type.is_a?(Array) ||
160
+ (resolver_type.is_a?(String) && resolver_type.include?("[")) ||
161
+ connection?
162
+ else
163
+ false
164
+ end
165
+ end
166
+
167
+ # This extension is applied to fields when {#connection?} is true.
168
+ #
169
+ # You can override it in your base field definition.
170
+ # @return [Class] A {FieldExtension} subclass for implementing pagination behavior.
171
+ # @example Configuring a custom extension
172
+ # class Types::BaseField < GraphQL::Schema::Field
173
+ # connection_extension(MyCustomExtension)
174
+ # end
175
+ def self.connection_extension(new_extension_class = nil)
176
+ if new_extension_class
177
+ @connection_extension = new_extension_class
132
178
  else
133
- @return_type_expr.is_a?(Array) || (@return_type_expr.is_a?(String) && @return_type_expr.include?("[")) || connection?
179
+ @connection_extension ||= find_inherited_value(:connection_extension, ConnectionExtension)
134
180
  end
135
181
  end
136
182
 
183
+ # @return Boolean
184
+ attr_reader :relay_node_field
185
+ # @return Boolean
186
+ attr_reader :relay_nodes_field
187
+
188
+ # @return [Boolean] Should we warn if this field's name conflicts with a built-in method?
189
+ def method_conflict_warning?
190
+ @method_conflict_warning
191
+ end
192
+
137
193
  # @param name [Symbol] The underscore-cased version of this field name (will be camelized for the GraphQL API)
138
194
  # @param type [Class, GraphQL::BaseType, Array] The return type of this field
139
195
  # @param owner [Class] The type that this field belongs to
140
- # @param null [Boolean] `true` if this field may return `null`, `false` if it is never `null`
196
+ # @param null [Boolean] (defaults to `true`) `true` if this field may return `null`, `false` if it is never `null`
141
197
  # @param description [String] Field description
142
198
  # @param deprecation_reason [String] If present, the field is marked "deprecated" with this message
143
199
  # @param method [Symbol] The method to call on the underlying object to resolve this field (defaults to `name`)
144
200
  # @param hash_key [String, Symbol] The hash key to lookup on the underlying object (if its a Hash) to resolve this field (defaults to `name` or `name.to_s`)
201
+ # @param dig [Array<String, Symbol>] The nested hash keys to lookup on the underlying hash to resolve this field using dig
145
202
  # @param resolver_method [Symbol] The method on the type to call to resolve this field (defaults to `name`)
146
203
  # @param connection [Boolean] `true` if this field should get automagic connection behavior; default is to infer by `*Connection` in the return type name
147
- # @param max_page_size [Integer] For connections, the maximum number of items to return from this field
204
+ # @param connection_extension [Class] The extension to add, to implement connections. If `nil`, no extension is added.
205
+ # @param max_page_size [Integer, nil] For connections, the maximum number of items to return from this field, or `nil` to allow unlimited results.
206
+ # @param default_page_size [Integer, nil] For connections, the default number of items to return from this field, or `nil` to return unlimited results.
148
207
  # @param introspection [Boolean] If true, this field will be marked as `#introspection?` and the name may begin with `__`
149
- # @param resolve [<#call(obj, args, ctx)>] **deprecated** for compatibility with <1.8.0
150
- # @param field [GraphQL::Field, GraphQL::Schema::Field] **deprecated** for compatibility with <1.8.0
151
- # @param function [GraphQL::Function] **deprecated** for compatibility with <1.8.0
152
208
  # @param resolver_class [Class] (Private) A {Schema::Resolver} which this field was derived from. Use `resolver:` to create a field with a resolver.
153
209
  # @param arguments [{String=>GraphQL::Schema::Argument, Hash}] Arguments for this field (may be added in the block, also)
154
210
  # @param camelize [Boolean] If true, the field name will be camelized when building the schema
155
211
  # @param complexity [Numeric] When provided, set the complexity for this field
156
212
  # @param scope [Boolean] If true, the return type's `.scope_items` method will be called on the return value
157
213
  # @param subscription_scope [Symbol, String] A key in `context` which will be used to scope subscription payloads
158
- # @param extensions [Array<Class>] Named extensions to apply to this field (see also {#extension})
214
+ # @param extensions [Array<Class, Hash<Class => Object>>] Named extensions to apply to this field (see also {#extension})
215
+ # @param directives [Hash{Class => Hash}] Directives to apply to this field
159
216
  # @param trace [Boolean] If true, a {GraphQL::Tracing} tracer will measure this scalar field
160
- def initialize(type: nil, name: nil, owner: nil, null: nil, field: nil, function: nil, description: nil, deprecation_reason: nil, method: nil, hash_key: nil, resolver_method: nil, resolve: nil, connection: nil, max_page_size: nil, scope: nil, introspection: false, camelize: true, trace: nil, complexity: 1, extras: [], extensions: [], resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, arguments: {}, &definition_block)
217
+ # @param broadcastable [Boolean] Whether or not this field can be distributed in subscription broadcasts
218
+ # @param ast_node [Language::Nodes::FieldDefinition, nil] If this schema was parsed from definition, this AST node defined the field
219
+ # @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
220
+ # @param validates [Array<Hash>] Configurations for validating this field
221
+ # @param fallback_value [Object] A fallback value if the method is not defined
222
+ def initialize(type: nil, name: nil, owner: nil, null: nil, description: NOT_CONFIGURED, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, connection: nil, max_page_size: NOT_CONFIGURED, default_page_size: NOT_CONFIGURED, scope: nil, introspection: false, camelize: true, trace: nil, complexity: nil, ast_node: nil, extras: EMPTY_ARRAY, extensions: EMPTY_ARRAY, connection_extension: self.class.connection_extension, resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, method_conflict_warning: true, broadcastable: NOT_CONFIGURED, arguments: EMPTY_HASH, directives: EMPTY_HASH, validates: EMPTY_ARRAY, fallback_value: NOT_CONFIGURED, dynamic_introspection: false, &definition_block)
161
223
  if name.nil?
162
224
  raise ArgumentError, "missing first `name` argument or keyword `name:`"
163
225
  end
164
- if !(field || function || resolver_class)
226
+ if !(resolver_class)
165
227
  if type.nil?
166
228
  raise ArgumentError, "missing second `type` argument or keyword `type:`"
167
229
  end
168
- if null.nil?
169
- raise ArgumentError, "missing keyword argument null:"
170
- end
171
- end
172
- if (field || function || resolve) && extras.any?
173
- raise ArgumentError, "keyword `extras:` may only be used with method-based resolve and class-based field such as mutation class, please remove `field:`, `function:` or `resolve:`"
174
230
  end
175
231
  @original_name = name
176
- @underscored_name = Member::BuildType.underscore(name.to_s)
177
- @name = camelize ? Member::BuildType.camelize(name.to_s) : name.to_s
232
+ name_s = -name.to_s
233
+
234
+ @underscored_name = -Member::BuildType.underscore(name_s)
235
+ @name = -(camelize ? Member::BuildType.camelize(name_s) : name_s)
236
+
178
237
  @description = description
179
- if field.is_a?(GraphQL::Schema::Field)
180
- raise ArgumentError, "Instead of passing a field as `field:`, use `add_field(field)` to add an already-defined field."
181
- else
182
- @field = field
183
- end
184
- @function = function
185
- @resolve = resolve
186
- @deprecation_reason = deprecation_reason
238
+ @type = @owner_type = @own_validators = @own_directives = @own_arguments = @arguments_statically_coercible = nil # these will be prepared later if necessary
187
239
 
188
- if method && hash_key
189
- raise ArgumentError, "Provide `method:` _or_ `hash_key:`, not both. (called with: `method: #{method.inspect}, hash_key: #{hash_key.inspect}`)"
240
+ self.deprecation_reason = deprecation_reason
241
+
242
+ if method && hash_key && dig
243
+ raise ArgumentError, "Provide `method:`, `hash_key:` _or_ `dig:`, not multiple. (called with: `method: #{method.inspect}, hash_key: #{hash_key.inspect}, dig: #{dig.inspect}`)"
190
244
  end
191
245
 
192
246
  if resolver_method
@@ -194,67 +248,123 @@ module GraphQL
194
248
  raise ArgumentError, "Provide `method:` _or_ `resolver_method:`, not both. (called with: `method: #{method.inspect}, resolver_method: #{resolver_method.inspect}`)"
195
249
  end
196
250
 
197
- if hash_key
198
- raise ArgumentError, "Provide `hash_key:` _or_ `resolver_method:`, not both. (called with: `hash_key: #{hash_key.inspect}, resolver_method: #{resolver_method.inspect}`)"
251
+ if hash_key || dig
252
+ raise ArgumentError, "Provide `hash_key:`, `dig:`, _or_ `resolver_method:`, not multiple. (called with: `hash_key: #{hash_key.inspect}, dig: #{dig.inspect}, resolver_method: #{resolver_method.inspect}`)"
199
253
  end
200
254
  end
201
255
 
202
- # TODO: I think non-string/symbol hash keys are wrongly normalized (eg `1` will not work)
203
- method_name = method || hash_key || @underscored_name
204
- resolver_method ||= @underscored_name
256
+ method_name = method || hash_key || name_s
257
+ @dig_keys = dig
258
+ if hash_key
259
+ @hash_key = hash_key
260
+ @hash_key_str = hash_key.to_s
261
+ else
262
+ @hash_key = NOT_CONFIGURED
263
+ @hash_key_str = NOT_CONFIGURED
264
+ end
205
265
 
206
- @method_str = method_name.to_s
266
+ @method_str = -method_name.to_s
207
267
  @method_sym = method_name.to_sym
208
- @resolver_method = resolver_method
268
+ @resolver_method = (resolver_method || name_s).to_sym
209
269
  @complexity = complexity
270
+ @dynamic_introspection = dynamic_introspection
210
271
  @return_type_expr = type
211
- @return_type_null = null
272
+ @return_type_null = if !null.nil?
273
+ null
274
+ elsif resolver_class
275
+ nil
276
+ else
277
+ true
278
+ end
212
279
  @connection = connection
213
280
  @max_page_size = max_page_size
281
+ @default_page_size = default_page_size
214
282
  @introspection = introspection
215
283
  @extras = extras
284
+ @broadcastable = broadcastable
216
285
  @resolver_class = resolver_class
217
286
  @scope = scope
218
287
  @trace = trace
219
288
  @relay_node_field = relay_node_field
220
289
  @relay_nodes_field = relay_nodes_field
290
+ @ast_node = ast_node
291
+ @method_conflict_warning = method_conflict_warning
292
+ @fallback_value = fallback_value
221
293
 
222
- # Override the default from HasArguments
223
- @own_arguments = {}
224
294
  arguments.each do |name, arg|
225
- if arg.is_a?(Hash)
295
+ case arg
296
+ when Hash
226
297
  argument(name: name, **arg)
298
+ when GraphQL::Schema::Argument
299
+ add_argument(arg)
300
+ when Array
301
+ arg.each { |a| add_argument(a) }
227
302
  else
228
- @own_arguments[name] = arg
303
+ raise ArgumentError, "Unexpected argument config (#{arg.class}): #{arg.inspect}"
229
304
  end
230
305
  end
231
306
 
232
307
  @owner = owner
233
308
  @subscription_scope = subscription_scope
234
309
 
235
- # Do this last so we have as much context as possible when initializing them:
236
- @extensions = []
237
- if extensions.any?
238
- self.extensions(extensions)
239
- end
310
+ @extensions = EMPTY_ARRAY
311
+ @call_after_define = false
240
312
  # This should run before connection extension,
241
313
  # but should it run after the definition block?
242
314
  if scoped?
243
315
  self.extension(ScopeExtension)
244
316
  end
317
+
245
318
  # The problem with putting this after the definition_block
246
319
  # is that it would override arguments
247
- if connection?
248
- self.extension(ConnectionExtension)
320
+ if connection? && connection_extension
321
+ self.extension(connection_extension)
322
+ end
323
+
324
+ # Do this last so we have as much context as possible when initializing them:
325
+ if extensions.any?
326
+ self.extensions(extensions)
249
327
  end
250
328
 
251
- if definition_block
329
+ if resolver_class && resolver_class.extensions.any?
330
+ self.extensions(resolver_class.extensions)
331
+ end
332
+
333
+ if directives.any?
334
+ directives.each do |(dir_class, options)|
335
+ self.directive(dir_class, **options)
336
+ end
337
+ end
338
+
339
+ if !validates.empty?
340
+ self.validates(validates)
341
+ end
342
+
343
+ if block_given?
252
344
  if definition_block.arity == 1
253
345
  yield self
254
346
  else
255
347
  instance_eval(&definition_block)
256
348
  end
257
349
  end
350
+
351
+ self.extensions.each(&:after_define_apply)
352
+ @call_after_define = true
353
+ end
354
+
355
+ attr_accessor :dynamic_introspection
356
+
357
+ # If true, subscription updates with this field can be shared between viewers
358
+ # @return [Boolean, nil]
359
+ # @see GraphQL::Subscriptions::BroadcastAnalyzer
360
+ def broadcastable?
361
+ if !NOT_CONFIGURED.equal?(@broadcastable)
362
+ @broadcastable
363
+ elsif @resolver_class
364
+ @resolver_class.broadcastable?
365
+ else
366
+ nil
367
+ end
258
368
  end
259
369
 
260
370
  # @param text [String]
@@ -262,55 +372,156 @@ module GraphQL
262
372
  def description(text = nil)
263
373
  if text
264
374
  @description = text
265
- else
375
+ elsif !NOT_CONFIGURED.equal?(@description)
266
376
  @description
377
+ elsif @resolver_class
378
+ @resolver_class.description
379
+ else
380
+ nil
267
381
  end
268
382
  end
269
383
 
270
384
  # Read extension instances from this field,
271
385
  # or add new classes/options to be initialized on this field.
386
+ # Extensions are executed in the order they are added.
387
+ #
388
+ # @example adding an extension
389
+ # extensions([MyExtensionClass])
390
+ #
391
+ # @example adding multiple extensions
392
+ # extensions([MyExtensionClass, AnotherExtensionClass])
393
+ #
394
+ # @example adding an extension with options
395
+ # extensions([MyExtensionClass, { AnotherExtensionClass => { filter: true } }])
272
396
  #
273
- # @param extensions [Array<Class>, Hash<Class => Object>] Add extensions to this field
397
+ # @param extensions [Array<Class, Hash<Class => Hash>>] Add extensions to this field. For hash elements, only the first key/value is used.
274
398
  # @return [Array<GraphQL::Schema::FieldExtension>] extensions to apply to this field
275
399
  def extensions(new_extensions = nil)
276
- if new_extensions.nil?
400
+ if new_extensions
401
+ new_extensions.each do |extension_config|
402
+ if extension_config.is_a?(Hash)
403
+ extension_class, options = *extension_config.to_a[0]
404
+ self.extension(extension_class, options)
405
+ else
406
+ self.extension(extension_config)
407
+ end
408
+ end
409
+ end
410
+ @extensions
411
+ end
412
+
413
+ # Add `extension` to this field, initialized with `options` if provided.
414
+ #
415
+ # @example adding an extension
416
+ # extension(MyExtensionClass)
417
+ #
418
+ # @example adding an extension with options
419
+ # extension(MyExtensionClass, filter: true)
420
+ #
421
+ # @param extension_class [Class] subclass of {Schema::FieldExtension}
422
+ # @param options [Hash] if provided, given as `options:` when initializing `extension`.
423
+ # @return [void]
424
+ def extension(extension_class, options = nil)
425
+ extension_inst = extension_class.new(field: self, options: options)
426
+ if @extensions.frozen?
427
+ @extensions = @extensions.dup
428
+ end
429
+ if @call_after_define
430
+ extension_inst.after_define_apply
431
+ end
432
+ @extensions << extension_inst
433
+ nil
434
+ end
435
+
436
+ # Read extras (as symbols) from this field,
437
+ # or add new extras to be opted into by this field's resolver.
438
+ #
439
+ # @param new_extras [Array<Symbol>] Add extras to this field
440
+ # @return [Array<Symbol>]
441
+ def extras(new_extras = nil)
442
+ if new_extras.nil?
277
443
  # Read the value
278
- @extensions
444
+ field_extras = @extras
445
+ if @resolver_class && @resolver_class.extras.any?
446
+ field_extras + @resolver_class.extras
447
+ else
448
+ field_extras
449
+ end
279
450
  else
280
- if @resolve || @function
281
- raise ArgumentError, <<-MSG
282
- Extensions are not supported with resolve procs or functions,
283
- but #{owner.name}.#{name} has: #{@resolve || @function}
284
- So, it can't have extensions: #{extensions}.
285
- Use a method or a Schema::Resolver instead.
286
- MSG
451
+ if @extras.frozen?
452
+ @extras = @extras.dup
287
453
  end
454
+ # Append to the set of extras on this field
455
+ @extras.concat(new_extras)
456
+ end
457
+ end
288
458
 
289
- # Normalize to a Hash of {name => options}
290
- extensions_with_options = if new_extensions.last.is_a?(Hash)
291
- new_extensions.pop
292
- else
293
- {}
459
+ def calculate_complexity(query:, nodes:, child_complexity:)
460
+ if respond_to?(:complexity_for)
461
+ lookahead = GraphQL::Execution::Lookahead.new(query: query, field: self, ast_nodes: nodes, owner_type: owner)
462
+ complexity_for(child_complexity: child_complexity, query: query, lookahead: lookahead)
463
+ elsif connection?
464
+ arguments = query.arguments_for(nodes.first, self)
465
+ max_possible_page_size = nil
466
+ if arguments.respond_to?(:[]) # It might have been an error
467
+ if arguments[:first]
468
+ max_possible_page_size = arguments[:first]
469
+ end
470
+
471
+ if arguments[:last] && (max_possible_page_size.nil? || arguments[:last] > max_possible_page_size)
472
+ max_possible_page_size = arguments[:last]
473
+ end
294
474
  end
295
- new_extensions.each do |f|
296
- extensions_with_options[f] = nil
475
+
476
+ if max_possible_page_size.nil?
477
+ max_possible_page_size = default_page_size || query.schema.default_page_size || max_page_size || query.schema.default_max_page_size
297
478
  end
298
479
 
299
- # Initialize each class and stash the instance
300
- extensions_with_options.each do |extension_class, options|
301
- @extensions << extension_class.new(field: self, options: options)
480
+ if max_possible_page_size.nil?
481
+ raise GraphQL::Error, "Can't calculate complexity for #{path}, no `first:`, `last:`, `default_page_size`, `max_page_size` or `default_max_page_size`"
482
+ else
483
+ metadata_complexity = 0
484
+ lookahead = GraphQL::Execution::Lookahead.new(query: query, field: self, ast_nodes: nodes, owner_type: owner)
485
+
486
+ if (page_info_lookahead = lookahead.selection(:page_info)).selected?
487
+ metadata_complexity += 1 # pageInfo
488
+ metadata_complexity += page_info_lookahead.selections.size # subfields
489
+ end
490
+
491
+ if lookahead.selects?(:total) || lookahead.selects?(:total_count) || lookahead.selects?(:count)
492
+ metadata_complexity += 1
493
+ end
494
+
495
+ nodes_edges_complexity = 0
496
+ nodes_edges_complexity += 1 if lookahead.selects?(:edges)
497
+ nodes_edges_complexity += 1 if lookahead.selects?(:nodes)
498
+
499
+ # Possible bug: selections on `edges` and `nodes` are _both_ multiplied here. Should they be?
500
+ items_complexity = child_complexity - metadata_complexity - nodes_edges_complexity
501
+ # Add 1 for _this_ field
502
+ 1 + (max_possible_page_size * items_complexity) + metadata_complexity + nodes_edges_complexity
302
503
  end
303
- end
304
- end
504
+ else
505
+ defined_complexity = complexity
506
+ case defined_complexity
507
+ when Proc
508
+ arguments = query.arguments_for(nodes.first, self)
509
+ if arguments.is_a?(GraphQL::ExecutionError)
510
+ return child_complexity
511
+ elsif arguments.respond_to?(:keyword_arguments)
512
+ arguments = arguments.keyword_arguments
513
+ end
305
514
 
306
- # Add `extension` to this field, initialized with `options` if provided.
307
- # @param extension [Class] subclass of {Schema::Fieldextension}
308
- # @param options [Object] if provided, given as `options:` when initializing `extension`.
309
- def extension(extension, options = nil)
310
- extensions([{extension => options}])
515
+ defined_complexity.call(query.context, arguments, child_complexity)
516
+ when Numeric
517
+ defined_complexity + child_complexity
518
+ else
519
+ raise("Invalid complexity: #{defined_complexity.inspect} on #{path} (#{inspect})")
520
+ end
521
+ end
311
522
  end
312
523
 
313
- def complexity(new_complexity)
524
+ def complexity(new_complexity = nil)
314
525
  case new_complexity
315
526
  when Proc
316
527
  if new_complexity.parameters.size != 3
@@ -323,87 +534,68 @@ MSG
323
534
  end
324
535
  when Numeric
325
536
  @complexity = new_complexity
537
+ when nil
538
+ if @resolver_class
539
+ @complexity || @resolver_class.complexity || 1
540
+ else
541
+ @complexity || 1
542
+ end
326
543
  else
327
544
  raise("Invalid complexity: #{new_complexity.inspect} on #{@name}")
328
545
  end
329
546
  end
330
547
 
331
- # @return [Integer, nil] Applied to connections if present
332
- attr_reader :max_page_size
548
+ # @return [Boolean] True if this field's {#max_page_size} should override the schema default.
549
+ def has_max_page_size?
550
+ !NOT_CONFIGURED.equal?(@max_page_size) || (@resolver_class && @resolver_class.has_max_page_size?)
551
+ end
333
552
 
334
- # @return [GraphQL::Field]
335
- def to_graphql
336
- field_defn = if @field
337
- @field.dup
338
- elsif @function
339
- GraphQL::Function.build_field(@function)
553
+ # @return [Integer, nil] Applied to connections if {#has_max_page_size?}
554
+ def max_page_size
555
+ if !NOT_CONFIGURED.equal?(@max_page_size)
556
+ @max_page_size
557
+ elsif @resolver_class && @resolver_class.has_max_page_size?
558
+ @resolver_class.max_page_size
340
559
  else
341
- GraphQL::Field.new
560
+ nil
342
561
  end
562
+ end
343
563
 
344
- field_defn.name = @name
345
- if @return_type_expr
346
- field_defn.type = -> { type }
347
- end
564
+ # @return [Boolean] True if this field's {#default_page_size} should override the schema default.
565
+ def has_default_page_size?
566
+ !NOT_CONFIGURED.equal?(@default_page_size) || (@resolver_class && @resolver_class.has_default_page_size?)
567
+ end
348
568
 
349
- if @description
350
- field_defn.description = @description
569
+ # @return [Integer, nil] Applied to connections if {#has_default_page_size?}
570
+ def default_page_size
571
+ if !NOT_CONFIGURED.equal?(@default_page_size)
572
+ @default_page_size
573
+ elsif @resolver_class && @resolver_class.has_default_page_size?
574
+ @resolver_class.default_page_size
575
+ else
576
+ nil
351
577
  end
578
+ end
352
579
 
353
- if @deprecation_reason
354
- field_defn.deprecation_reason = @deprecation_reason
355
- end
580
+ class MissingReturnTypeError < GraphQL::Error; end
581
+ attr_writer :type
356
582
 
583
+ def type
357
584
  if @resolver_class
358
- if @resolver_class < GraphQL::Schema::Mutation
359
- field_defn.mutation = @resolver_class
585
+ return_type = @return_type_expr || @resolver_class.type_expr
586
+ if return_type.nil?
587
+ raise MissingReturnTypeError, "Can't determine the return type for #{self.path} (it has `resolver: #{@resolver_class}`, perhaps that class is missing a `type ...` declaration, or perhaps its type causes a cyclical loading issue)"
360
588
  end
361
- field_defn.metadata[:resolver] = @resolver_class
362
- end
363
-
364
- if !@trace.nil?
365
- field_defn.trace = @trace
366
- end
367
-
368
- if @relay_node_field
369
- field_defn.relay_node_field = @relay_node_field
370
- end
371
-
372
- if @relay_nodes_field
373
- field_defn.relay_nodes_field = @relay_nodes_field
374
- end
375
-
376
- field_defn.resolve = self.method(:resolve_field)
377
- field_defn.connection = connection?
378
- field_defn.connection_max_page_size = max_page_size
379
- field_defn.introspection = @introspection
380
- field_defn.complexity = @complexity
381
- field_defn.subscription_scope = @subscription_scope
382
-
383
- arguments.each do |name, defn|
384
- arg_graphql = defn.to_graphql
385
- field_defn.arguments[arg_graphql.name] = arg_graphql
386
- end
387
-
388
- # Support a passed-in proc, one way or another
389
- @resolve_proc = if @resolve
390
- @resolve
391
- elsif @function
392
- @function
393
- elsif @field
394
- @field.resolve_proc
589
+ nullable = @return_type_null.nil? ? @resolver_class.null : @return_type_null
590
+ Member::BuildType.parse_type(return_type, null: nullable)
591
+ else
592
+ @type ||= Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
395
593
  end
396
-
397
- # Ok, `self` isn't a class, but this is for consistency with the classes
398
- field_defn.metadata[:type_class] = self
399
-
400
- field_defn
401
- end
402
-
403
- def type
404
- @type ||= Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
405
- rescue
406
- raise ArgumentError, "Failed to build return type for #{@owner.graphql_name}.#{name} from #{@return_type_expr.inspect}: #{$!.message}", $!.backtrace
594
+ rescue GraphQL::Schema::InvalidDocumentError, MissingReturnTypeError => err
595
+ # Let this propagate up
596
+ raise err
597
+ rescue StandardError => err
598
+ raise MissingReturnTypeError, "Failed to build return type for #{@owner.graphql_name}.#{name} from #{@return_type_expr.inspect}: (#{err.class}) #{err.message}", err.backtrace
407
599
  end
408
600
 
409
601
  def visible?(context)
@@ -414,57 +606,47 @@ MSG
414
606
  end
415
607
  end
416
608
 
417
- def accessible?(context)
609
+ def authorized?(object, args, context)
418
610
  if @resolver_class
419
- @resolver_class.accessible?(context)
420
- else
421
- true
422
- end
423
- end
424
-
425
- def authorized?(object, context)
426
- self_auth = if @resolver_class
611
+ # The resolver _instance_ will check itself during `resolve()`
427
612
  @resolver_class.authorized?(object, context)
428
613
  else
429
- true
430
- end
431
-
432
- if self_auth
433
- # Faster than `.any?`
434
- arguments.each_value do |arg|
435
- if !arg.authorized?(object, context)
436
- return false
614
+ if args.size > 0
615
+ if (arg_values = context[:current_arguments])
616
+ # ^^ that's provided by the interpreter at runtime, and includes info about whether the default value was used or not.
617
+ using_arg_values = true
618
+ arg_values = arg_values.argument_values
619
+ else
620
+ arg_values = args
621
+ using_arg_values = false
437
622
  end
438
- end
439
- true
440
- else
441
- false
442
- end
443
- end
444
623
 
445
- # Implement {GraphQL::Field}'s resolve API.
446
- #
447
- # Eventually, we might hook up field instances to execution in another way. TBD.
448
- # @see #resolve for how the interpreter hooks up to it
449
- def resolve_field(obj, args, ctx)
450
- ctx.schema.after_lazy(obj) do |after_obj|
451
- # First, apply auth ...
452
- query_ctx = ctx.query.context
453
- # Some legacy fields can have `nil` here, not exactly sure why.
454
- # @see https://github.com/rmosolgo/graphql-ruby/issues/1990 before removing
455
- inner_obj = after_obj && after_obj.object
456
- if authorized?(inner_obj, query_ctx)
457
- # Then if it passed, resolve the field
458
- if @resolve_proc
459
- # Might be nil, still want to call the func in that case
460
- @resolve_proc.call(inner_obj, args, ctx)
461
- else
462
- public_send_field(after_obj, args, ctx)
624
+ args = context.warden.arguments(self)
625
+ args.each do |arg|
626
+ arg_key = arg.keyword
627
+ if arg_values.key?(arg_key)
628
+ arg_value = arg_values[arg_key]
629
+ if using_arg_values
630
+ if arg_value.default_used?
631
+ # pass -- no auth required for default used
632
+ next
633
+ else
634
+ application_arg_value = arg_value.value
635
+ if application_arg_value.is_a?(GraphQL::Execution::Interpreter::Arguments)
636
+ application_arg_value.keyword_arguments
637
+ end
638
+ end
639
+ else
640
+ application_arg_value = arg_value
641
+ end
642
+
643
+ if !arg.authorized?(object, application_arg_value, context)
644
+ return false
645
+ end
646
+ end
463
647
  end
464
- else
465
- err = GraphQL::UnauthorizedFieldError.new(object: inner_obj, type: obj.class, context: ctx, field: self)
466
- query_ctx.schema.unauthorized_field(err)
467
648
  end
649
+ true
468
650
  end
469
651
  end
470
652
 
@@ -473,141 +655,175 @@ MSG
473
655
  # @param object [GraphQL::Schema::Object] An instance of some type class, wrapping an application object
474
656
  # @param args [Hash] A symbol-keyed hash of Ruby keyword arguments. (Empty if no args)
475
657
  # @param ctx [GraphQL::Query::Context]
476
- def resolve(object, args, ctx)
477
- if @resolve_proc
478
- raise "Can't run resolve proc for #{path} when using GraphQL::Execution::Interpreter"
479
- end
480
- begin
481
- # Unwrap the GraphQL object to get the application object.
482
- application_object = object.object
483
- if self.authorized?(application_object, ctx)
484
- # Apply field extensions
485
- with_extensions(object, args, ctx) do |extended_obj, extended_args|
486
- field_receiver = if @resolver_class
487
- resolver_obj = if extended_obj.is_a?(GraphQL::Schema::Object)
488
- extended_obj.object
489
- else
490
- extended_obj
658
+ def resolve(object, args, query_ctx)
659
+ # Unwrap the GraphQL object to get the application object.
660
+ application_object = object.object
661
+ method_receiver = nil
662
+ method_to_call = nil
663
+ method_args = nil
664
+
665
+ @own_validators && Schema::Validator.validate!(validators, application_object, query_ctx, args)
666
+
667
+ query_ctx.query.after_lazy(self.authorized?(application_object, args, query_ctx)) do |is_authorized|
668
+ if is_authorized
669
+ with_extensions(object, args, query_ctx) do |obj, ruby_kwargs|
670
+ method_args = ruby_kwargs
671
+ if @resolver_class
672
+ if obj.is_a?(GraphQL::Schema::Object)
673
+ obj = obj.object
491
674
  end
492
- @resolver_class.new(object: resolver_obj, context: ctx)
493
- else
494
- extended_obj
675
+ obj = @resolver_class.new(object: obj, context: query_ctx, field: self)
495
676
  end
496
677
 
497
- if field_receiver.respond_to?(@resolver_method)
678
+ inner_object = obj.object
679
+
680
+ if !NOT_CONFIGURED.equal?(@hash_key)
681
+ hash_value = if inner_object.is_a?(Hash)
682
+ inner_object.key?(@hash_key) ? inner_object[@hash_key] : inner_object[@hash_key_str]
683
+ elsif inner_object.respond_to?(:[])
684
+ inner_object[@hash_key]
685
+ else
686
+ nil
687
+ end
688
+ if hash_value == false
689
+ hash_value
690
+ else
691
+ hash_value || (@fallback_value != NOT_CONFIGURED ? @fallback_value : nil)
692
+ end
693
+ elsif obj.respond_to?(resolver_method)
694
+ method_to_call = resolver_method
695
+ method_receiver = obj
498
696
  # Call the method with kwargs, if there are any
499
- if extended_args.any?
500
- field_receiver.public_send(@resolver_method, **extended_args)
697
+ if ruby_kwargs.any?
698
+ obj.public_send(resolver_method, **ruby_kwargs)
699
+ else
700
+ obj.public_send(resolver_method)
701
+ end
702
+ elsif inner_object.is_a?(Hash)
703
+ if @dig_keys
704
+ inner_object.dig(*@dig_keys)
705
+ elsif inner_object.key?(@method_sym)
706
+ inner_object[@method_sym]
707
+ elsif inner_object.key?(@method_str)
708
+ inner_object[@method_str]
709
+ elsif @fallback_value != NOT_CONFIGURED
710
+ @fallback_value
501
711
  else
502
- field_receiver.public_send(@resolver_method)
712
+ nil
503
713
  end
714
+ elsif inner_object.respond_to?(@method_sym)
715
+ method_to_call = @method_sym
716
+ method_receiver = obj.object
717
+ if ruby_kwargs.any?
718
+ inner_object.public_send(@method_sym, **ruby_kwargs)
719
+ else
720
+ inner_object.public_send(@method_sym)
721
+ end
722
+ elsif @fallback_value != NOT_CONFIGURED
723
+ @fallback_value
504
724
  else
505
- resolve_field_method(field_receiver, extended_args, ctx)
725
+ raise <<-ERR
726
+ Failed to implement #{@owner.graphql_name}.#{@name}, tried:
727
+
728
+ - `#{obj.class}##{resolver_method}`, which did not exist
729
+ - `#{inner_object.class}##{@method_sym}`, which did not exist
730
+ - Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{inner_object}`, but it wasn't a Hash
731
+
732
+ To implement this field, define one of the methods above (and check for typos), or supply a `fallback_value`.
733
+ ERR
506
734
  end
507
735
  end
508
736
  else
509
- err = GraphQL::UnauthorizedFieldError.new(object: application_object, type: object.class, context: ctx, field: self)
510
- ctx.schema.unauthorized_field(err)
737
+ raise GraphQL::UnauthorizedFieldError.new(object: application_object, type: object.class, context: query_ctx, field: self)
511
738
  end
512
- rescue GraphQL::UnauthorizedError => err
513
- ctx.schema.unauthorized_object(err)
514
739
  end
740
+ rescue GraphQL::UnauthorizedFieldError => err
741
+ err.field ||= self
742
+ begin
743
+ query_ctx.schema.unauthorized_field(err)
744
+ rescue GraphQL::ExecutionError => err
745
+ err
746
+ end
747
+ rescue GraphQL::UnauthorizedError => err
748
+ begin
749
+ query_ctx.schema.unauthorized_object(err)
750
+ rescue GraphQL::ExecutionError => err
751
+ err
752
+ end
753
+ rescue ArgumentError
754
+ if method_receiver && method_to_call
755
+ assert_satisfactory_implementation(method_receiver, method_to_call, method_args)
756
+ end
757
+ # if the line above doesn't raise, re-raise
758
+ raise
515
759
  rescue GraphQL::ExecutionError => err
516
760
  err
517
761
  end
518
762
 
519
- # Find a way to resolve this field, checking:
520
- #
521
- # - Hash keys, if the wrapped object is a hash;
522
- # - A method on the wrapped object;
523
- # - Or, raise not implemented.
524
- #
525
- # This can be overridden by defining a method on the object type.
526
- # @param obj [GraphQL::Schema::Object]
527
- # @param ruby_kwargs [Hash<Symbol => Object>]
528
763
  # @param ctx [GraphQL::Query::Context]
529
- def resolve_field_method(obj, ruby_kwargs, ctx)
530
- if obj.object.is_a?(Hash)
531
- inner_object = obj.object
532
- if inner_object.key?(@method_sym)
533
- inner_object[@method_sym]
534
- else
535
- inner_object[@method_str]
536
- end
537
- elsif obj.object.respond_to?(@method_sym)
538
- if ruby_kwargs.any?
539
- obj.object.public_send(@method_sym, **ruby_kwargs)
540
- else
541
- obj.object.public_send(@method_sym)
542
- end
543
- else
544
- raise <<-ERR
545
- Failed to implement #{@owner.graphql_name}.#{@name}, tried:
546
-
547
- - `#{obj.class}##{@resolver_method}`, which did not exist
548
- - `#{obj.object.class}##{@method_sym}`, which did not exist
549
- - Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{obj.object}`, but it wasn't a Hash
550
-
551
- To implement this field, define one of the methods above (and check for typos)
552
- ERR
553
- end
554
- end
555
-
556
- # @param ctx [GraphQL::Query::Context::FieldResolutionContext]
557
764
  def fetch_extra(extra_name, ctx)
558
- if extra_name != :path && respond_to?(extra_name)
765
+ if extra_name != :path && extra_name != :ast_node && respond_to?(extra_name)
559
766
  self.public_send(extra_name)
560
767
  elsif ctx.respond_to?(extra_name)
561
768
  ctx.public_send(extra_name)
562
769
  else
563
- raise NotImplementedError, "Unknown field extra for #{self.path}: #{extra_name.inspect}"
770
+ raise GraphQL::RequiredImplementationMissingError, "Unknown field extra for #{self.path}: #{extra_name.inspect}"
564
771
  end
565
772
  end
566
773
 
567
774
  private
568
775
 
569
- NO_ARGS = {}.freeze
570
-
571
- def public_send_field(obj, graphql_args, field_ctx)
572
- if graphql_args.any? || @extras.any?
573
- # Splat the GraphQL::Arguments to Ruby keyword arguments
574
- ruby_kwargs = graphql_args.to_kwargs
575
- # Apply any `prepare` methods. Not great code organization, can this go somewhere better?
576
- arguments.each do |name, arg_defn|
577
- ruby_kwargs_key = arg_defn.keyword
578
- if ruby_kwargs.key?(ruby_kwargs_key) && arg_defn.prepare
579
- ruby_kwargs[ruby_kwargs_key] = arg_defn.prepare_value(obj, ruby_kwargs[ruby_kwargs_key])
776
+ def assert_satisfactory_implementation(receiver, method_name, ruby_kwargs)
777
+ method_defn = receiver.method(method_name)
778
+ unsatisfied_ruby_kwargs = ruby_kwargs.dup
779
+ unsatisfied_method_params = []
780
+ encountered_keyrest = false
781
+ method_defn.parameters.each do |(param_type, param_name)|
782
+ case param_type
783
+ when :key
784
+ unsatisfied_ruby_kwargs.delete(param_name)
785
+ when :keyreq
786
+ if unsatisfied_ruby_kwargs.key?(param_name)
787
+ unsatisfied_ruby_kwargs.delete(param_name)
788
+ else
789
+ unsatisfied_method_params << "- `#{param_name}:` is required by Ruby, but not by GraphQL. Consider `#{param_name}: nil` instead, or making this argument required in GraphQL."
580
790
  end
791
+ when :keyrest
792
+ encountered_keyrest = true
793
+ when :req
794
+ unsatisfied_method_params << "- `#{param_name}` is required by Ruby, but GraphQL doesn't pass positional arguments. If it's meant to be a GraphQL argument, use `#{param_name}:` instead. Otherwise, remove it."
795
+ when :opt, :rest
796
+ # This is fine, although it will never be present
581
797
  end
798
+ end
582
799
 
583
- @extras.each do |extra_arg|
584
- ruby_kwargs[extra_arg] = fetch_extra(extra_arg, field_ctx)
585
- end
586
- else
587
- ruby_kwargs = NO_ARGS
800
+ if encountered_keyrest
801
+ unsatisfied_ruby_kwargs.clear
588
802
  end
589
803
 
590
- query_ctx = field_ctx.query.context
591
- with_extensions(obj, ruby_kwargs, query_ctx) do |extended_obj, extended_args|
592
- if @resolver_class
593
- if extended_obj.is_a?(GraphQL::Schema::Object)
594
- extended_obj = extended_obj.object
595
- end
596
- extended_obj = @resolver_class.new(object: extended_obj, context: query_ctx)
597
- end
804
+ if unsatisfied_ruby_kwargs.any? || unsatisfied_method_params.any?
805
+ raise FieldImplementationFailed.new, <<-ERR
806
+ Failed to call `#{method_name.inspect}` on #{receiver.inspect} because the Ruby method params were incompatible with the GraphQL arguments:
598
807
 
599
- if extended_obj.respond_to?(@resolver_method)
600
- if extended_args.any?
601
- extended_obj.public_send(@resolver_method, **extended_args)
602
- else
603
- extended_obj.public_send(@resolver_method)
604
- end
605
- else
606
- resolve_field_method(extended_obj, extended_args, query_ctx)
607
- end
808
+ #{ unsatisfied_ruby_kwargs
809
+ .map { |key, value| "- `#{key}: #{value}` was given by GraphQL but not defined in the Ruby method. Add `#{key}:` to the method parameters." }
810
+ .concat(unsatisfied_method_params)
811
+ .join("\n") }
812
+ ERR
608
813
  end
609
814
  end
610
815
 
816
+ class ExtendedState
817
+ def initialize(args, object)
818
+ @arguments = args
819
+ @object = object
820
+ @memos = nil
821
+ @added_extras = nil
822
+ end
823
+
824
+ attr_accessor :arguments, :object, :memos, :added_extras
825
+ end
826
+
611
827
  # Wrap execution with hooks.
612
828
  # Written iteratively to avoid big stack traces.
613
829
  # @return [Object] Whatever the
@@ -615,32 +831,52 @@ MSG
615
831
  if @extensions.empty?
616
832
  yield(obj, args)
617
833
  else
618
- # Save these so that the originals can be re-given to `after_resolve` handlers.
619
- original_args = args
620
- original_obj = obj
621
-
622
- memos = []
623
- value = run_extensions_before_resolve(memos, obj, args, ctx) do |extended_obj, extended_args|
624
- yield(extended_obj, extended_args)
834
+ # This is a hack to get the _last_ value for extended obj and args,
835
+ # in case one of the extensions doesn't `yield`.
836
+ # (There's another implementation that uses multiple-return, but I'm wary of the perf cost of the extra arrays)
837
+ extended = ExtendedState.new(args, obj)
838
+ value = run_extensions_before_resolve(obj, args, ctx, extended) do |obj, args|
839
+ if (added_extras = extended.added_extras)
840
+ args = args.dup
841
+ added_extras.each { |e| args.delete(e) }
842
+ end
843
+ yield(obj, args)
625
844
  end
626
845
 
627
- ctx.schema.after_lazy(value) do |resolved_value|
628
- @extensions.each_with_index do |ext, idx|
846
+ extended_obj = extended.object
847
+ extended_args = extended.arguments # rubocop:disable Development/ContextIsPassedCop
848
+ memos = extended.memos || EMPTY_HASH
849
+
850
+ ctx.query.after_lazy(value) do |resolved_value|
851
+ idx = 0
852
+ @extensions.each do |ext|
629
853
  memo = memos[idx]
630
854
  # TODO after_lazy?
631
- resolved_value = ext.after_resolve(object: original_obj, arguments: original_args, context: ctx, value: resolved_value, memo: memo)
855
+ resolved_value = ext.after_resolve(object: extended_obj, arguments: extended_args, context: ctx, value: resolved_value, memo: memo)
856
+ idx += 1
632
857
  end
633
858
  resolved_value
634
859
  end
635
860
  end
636
861
  end
637
862
 
638
- def run_extensions_before_resolve(memos, obj, args, ctx, idx: 0)
863
+ def run_extensions_before_resolve(obj, args, ctx, extended, idx: 0)
639
864
  extension = @extensions[idx]
640
865
  if extension
641
866
  extension.resolve(object: obj, arguments: args, context: ctx) do |extended_obj, extended_args, memo|
642
- memos << memo
643
- run_extensions_before_resolve(memos, extended_obj, extended_args, ctx, idx: idx + 1) { |o, a| yield(o, a) }
867
+ if memo
868
+ memos = extended.memos ||= {}
869
+ memos[idx] = memo
870
+ end
871
+
872
+ if (extras = extension.added_extras)
873
+ ae = extended.added_extras ||= []
874
+ ae.concat(extras)
875
+ end
876
+
877
+ extended.object = extended_obj
878
+ extended.arguments = extended_args
879
+ run_extensions_before_resolve(extended_obj, extended_args, ctx, extended, idx: idx + 1) { |o, a| yield(o, a) }
644
880
  end
645
881
  else
646
882
  yield(obj, args)