graphql 1.9.0 → 2.1.1

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