graphql 1.9.21 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of graphql might be problematic. Click here for more details.

Files changed (397) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +21 -10
  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/{templates → install/templates}/base_mutation.erb +2 -0
  8. data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +2 -0
  9. data/lib/generators/graphql/install_generator.rb +44 -7
  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 +63 -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 +2 -0
  22. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  23. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  24. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  25. data/lib/generators/graphql/templates/base_field.erb +2 -0
  26. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  27. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  28. data/lib/generators/graphql/templates/base_object.erb +2 -0
  29. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  30. data/lib/generators/graphql/templates/base_union.erb +2 -0
  31. data/lib/generators/graphql/templates/enum.erb +7 -1
  32. data/lib/generators/graphql/templates/graphql_controller.erb +16 -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 +2 -0
  36. data/lib/generators/graphql/templates/mutation.erb +3 -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 +9 -0
  41. data/lib/generators/graphql/templates/object.erb +7 -3
  42. data/lib/generators/graphql/templates/query_type.erb +3 -3
  43. data/lib/generators/graphql/templates/scalar.erb +5 -1
  44. data/lib/generators/graphql/templates/schema.erb +22 -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/field_usage.rb +29 -2
  49. data/lib/graphql/analysis/ast/query_complexity.rb +175 -68
  50. data/lib/graphql/analysis/ast/query_depth.rb +0 -1
  51. data/lib/graphql/analysis/ast/visitor.rb +17 -8
  52. data/lib/graphql/analysis/ast.rb +14 -14
  53. data/lib/graphql/analysis.rb +0 -7
  54. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  55. data/lib/graphql/backtrace/table.rb +37 -16
  56. data/lib/graphql/backtrace/traced_error.rb +0 -1
  57. data/lib/graphql/backtrace/tracer.rb +39 -9
  58. data/lib/graphql/backtrace.rb +20 -17
  59. data/lib/graphql/dataloader/null_dataloader.rb +22 -0
  60. data/lib/graphql/dataloader/request.rb +19 -0
  61. data/lib/graphql/dataloader/request_all.rb +19 -0
  62. data/lib/graphql/dataloader/source.rb +155 -0
  63. data/lib/graphql/dataloader.rb +308 -0
  64. data/lib/graphql/date_encoding_error.rb +16 -0
  65. data/lib/graphql/deprecation.rb +9 -0
  66. data/lib/graphql/dig.rb +1 -1
  67. data/lib/graphql/execution/directive_checks.rb +2 -2
  68. data/lib/graphql/execution/errors.rb +108 -14
  69. data/lib/graphql/execution/instrumentation.rb +1 -1
  70. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  71. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  72. data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
  73. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  74. data/lib/graphql/execution/interpreter/resolve.rb +37 -25
  75. data/lib/graphql/execution/interpreter/runtime.rb +715 -387
  76. data/lib/graphql/execution/interpreter.rb +32 -31
  77. data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
  78. data/lib/graphql/execution/lazy.rb +5 -1
  79. data/lib/graphql/execution/lookahead.rb +32 -114
  80. data/lib/graphql/execution/multiplex.rb +60 -92
  81. data/lib/graphql/execution.rb +11 -3
  82. data/lib/graphql/filter.rb +1 -1
  83. data/lib/graphql/integer_decoding_error.rb +17 -0
  84. data/lib/graphql/integer_encoding_error.rb +18 -2
  85. data/lib/graphql/introspection/base_object.rb +2 -5
  86. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  87. data/lib/graphql/introspection/directive_type.rb +11 -5
  88. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  89. data/lib/graphql/introspection/entry_points.rb +5 -18
  90. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  91. data/lib/graphql/introspection/field_type.rb +9 -5
  92. data/lib/graphql/introspection/input_value_type.rb +41 -11
  93. data/lib/graphql/introspection/introspection_query.rb +6 -92
  94. data/lib/graphql/introspection/schema_type.rb +10 -10
  95. data/lib/graphql/introspection/type_type.rb +27 -17
  96. data/lib/graphql/introspection.rb +99 -0
  97. data/lib/graphql/invalid_null_error.rb +18 -0
  98. data/lib/graphql/language/block_string.rb +20 -5
  99. data/lib/graphql/language/cache.rb +37 -0
  100. data/lib/graphql/language/definition_slice.rb +21 -10
  101. data/lib/graphql/language/document_from_schema_definition.rb +99 -63
  102. data/lib/graphql/language/lexer.rb +53 -27
  103. data/lib/graphql/language/lexer.rl +5 -3
  104. data/lib/graphql/language/nodes.rb +64 -93
  105. data/lib/graphql/language/parser.rb +929 -896
  106. data/lib/graphql/language/parser.y +125 -102
  107. data/lib/graphql/language/printer.rb +11 -2
  108. data/lib/graphql/language/sanitized_printer.rb +222 -0
  109. data/lib/graphql/language/token.rb +0 -4
  110. data/lib/graphql/language/visitor.rb +2 -2
  111. data/lib/graphql/language.rb +3 -1
  112. data/lib/graphql/name_validator.rb +2 -7
  113. data/lib/graphql/pagination/active_record_relation_connection.rb +85 -0
  114. data/lib/graphql/pagination/array_connection.rb +77 -0
  115. data/lib/graphql/pagination/connection.rb +226 -0
  116. data/lib/graphql/pagination/connections.rb +134 -0
  117. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  118. data/lib/graphql/pagination/relation_connection.rb +226 -0
  119. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  120. data/lib/graphql/pagination.rb +6 -0
  121. data/lib/graphql/parse_error.rb +0 -1
  122. data/lib/graphql/query/context.rb +51 -190
  123. data/lib/graphql/query/fingerprint.rb +26 -0
  124. data/lib/graphql/query/input_validation_result.rb +23 -6
  125. data/lib/graphql/query/literal_input.rb +26 -11
  126. data/lib/graphql/query/null_context.rb +24 -8
  127. data/lib/graphql/query/validation_pipeline.rb +12 -38
  128. data/lib/graphql/query/variable_validation_error.rb +2 -2
  129. data/lib/graphql/query/variables.rb +26 -9
  130. data/lib/graphql/query.rb +62 -32
  131. data/lib/graphql/railtie.rb +6 -102
  132. data/lib/graphql/rake_task/validate.rb +3 -0
  133. data/lib/graphql/rake_task.rb +12 -9
  134. data/lib/graphql/relay/range_add.rb +23 -9
  135. data/lib/graphql/relay.rb +0 -15
  136. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  137. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  138. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  139. data/lib/graphql/rubocop.rb +4 -0
  140. data/lib/graphql/schema/addition.rb +240 -0
  141. data/lib/graphql/schema/argument.rb +262 -28
  142. data/lib/graphql/schema/base_64_encoder.rb +2 -0
  143. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
  144. data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
  145. data/lib/graphql/schema/build_from_definition.rb +319 -220
  146. data/lib/graphql/schema/built_in_types.rb +5 -5
  147. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  148. data/lib/graphql/schema/directive/feature.rb +1 -1
  149. data/lib/graphql/schema/directive/flagged.rb +57 -0
  150. data/lib/graphql/schema/directive/include.rb +2 -2
  151. data/lib/graphql/schema/directive/skip.rb +2 -2
  152. data/lib/graphql/schema/directive/transform.rb +14 -2
  153. data/lib/graphql/schema/directive.rb +117 -14
  154. data/lib/graphql/schema/enum.rb +115 -22
  155. data/lib/graphql/schema/enum_value.rb +16 -21
  156. data/lib/graphql/schema/field/connection_extension.rb +46 -20
  157. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  158. data/lib/graphql/schema/field.rb +376 -291
  159. data/lib/graphql/schema/field_extension.rb +89 -2
  160. data/lib/graphql/schema/find_inherited_value.rb +17 -1
  161. data/lib/graphql/schema/finder.rb +16 -14
  162. data/lib/graphql/schema/input_object.rb +147 -60
  163. data/lib/graphql/schema/interface.rb +28 -43
  164. data/lib/graphql/schema/introspection_system.rb +101 -38
  165. data/lib/graphql/schema/late_bound_type.rb +3 -2
  166. data/lib/graphql/schema/list.rb +46 -3
  167. data/lib/graphql/schema/loader.rb +144 -102
  168. data/lib/graphql/schema/member/base_dsl_methods.rb +33 -32
  169. data/lib/graphql/schema/member/build_type.rb +23 -14
  170. data/lib/graphql/schema/member/has_arguments.rb +212 -23
  171. data/lib/graphql/schema/member/has_ast_node.rb +20 -0
  172. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  173. data/lib/graphql/schema/member/has_directives.rb +98 -0
  174. data/lib/graphql/schema/member/has_fields.rb +99 -34
  175. data/lib/graphql/schema/member/has_interfaces.rb +88 -0
  176. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  177. data/lib/graphql/schema/member/has_validators.rb +31 -0
  178. data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
  179. data/lib/graphql/schema/member/validates_input.rb +33 -0
  180. data/lib/graphql/schema/member.rb +11 -6
  181. data/lib/graphql/schema/mutation.rb +4 -9
  182. data/lib/graphql/schema/non_null.rb +34 -4
  183. data/lib/graphql/schema/object.rb +38 -65
  184. data/lib/graphql/schema/printer.rb +16 -35
  185. data/lib/graphql/schema/relay_classic_mutation.rb +57 -32
  186. data/lib/graphql/schema/resolver/has_payload_type.rb +34 -4
  187. data/lib/graphql/schema/resolver.rb +133 -79
  188. data/lib/graphql/schema/scalar.rb +40 -15
  189. data/lib/graphql/schema/subscription.rb +57 -21
  190. data/lib/graphql/schema/timeout.rb +29 -15
  191. data/lib/graphql/schema/type_expression.rb +21 -13
  192. data/lib/graphql/schema/type_membership.rb +19 -5
  193. data/lib/graphql/schema/union.rb +39 -14
  194. data/lib/graphql/schema/unique_within_type.rb +1 -2
  195. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  196. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  197. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  198. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  199. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  200. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  201. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  202. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  203. data/lib/graphql/schema/validator.rb +171 -0
  204. data/lib/graphql/schema/warden.rb +182 -32
  205. data/lib/graphql/schema/wrapper.rb +0 -5
  206. data/lib/graphql/schema.rb +687 -891
  207. data/lib/graphql/static_validation/all_rules.rb +2 -0
  208. data/lib/graphql/static_validation/base_visitor.rb +21 -31
  209. data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
  210. data/lib/graphql/static_validation/error.rb +3 -1
  211. data/lib/graphql/static_validation/literal_validator.rb +51 -26
  212. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +45 -83
  213. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +22 -6
  214. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +35 -26
  215. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  216. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
  217. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +14 -14
  218. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
  219. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
  220. data/lib/graphql/static_validation/rules/fields_will_merge.rb +94 -51
  221. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  222. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  223. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  224. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  225. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  226. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  227. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  228. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -2
  229. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +9 -10
  230. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
  231. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
  232. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -14
  233. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  234. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
  235. data/lib/graphql/static_validation/type_stack.rb +2 -2
  236. data/lib/graphql/static_validation/validation_context.rb +13 -3
  237. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  238. data/lib/graphql/static_validation/validator.rb +31 -19
  239. data/lib/graphql/static_validation.rb +1 -2
  240. data/lib/graphql/string_encoding_error.rb +13 -3
  241. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +123 -22
  242. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  243. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +58 -0
  244. data/lib/graphql/subscriptions/event.rb +85 -31
  245. data/lib/graphql/subscriptions/instrumentation.rb +0 -47
  246. data/lib/graphql/subscriptions/serialize.rb +53 -6
  247. data/lib/graphql/subscriptions.rb +111 -52
  248. data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
  249. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  250. data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
  251. data/lib/graphql/tracing/data_dog_tracing.rb +14 -1
  252. data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
  253. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  254. data/lib/graphql/tracing/platform_tracing.rb +57 -29
  255. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  256. data/lib/graphql/tracing/prometheus_tracing.rb +8 -0
  257. data/lib/graphql/tracing/scout_tracing.rb +19 -0
  258. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  259. data/lib/graphql/tracing.rb +15 -36
  260. data/lib/graphql/types/big_int.rb +5 -1
  261. data/lib/graphql/types/int.rb +10 -3
  262. data/lib/graphql/types/iso_8601_date.rb +16 -8
  263. data/lib/graphql/types/iso_8601_date_time.rb +32 -10
  264. data/lib/graphql/types/relay/base_connection.rb +6 -88
  265. data/lib/graphql/types/relay/base_edge.rb +2 -34
  266. data/lib/graphql/types/relay/connection_behaviors.rb +170 -0
  267. data/lib/graphql/types/relay/default_relay.rb +21 -0
  268. data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
  269. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  270. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  271. data/lib/graphql/types/relay/node.rb +2 -4
  272. data/lib/graphql/types/relay/node_behaviors.rb +19 -0
  273. data/lib/graphql/types/relay/page_info.rb +2 -14
  274. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  275. data/lib/graphql/types/relay.rb +11 -5
  276. data/lib/graphql/types/string.rb +8 -2
  277. data/lib/graphql/unauthorized_error.rb +2 -2
  278. data/lib/graphql/unresolved_type_error.rb +2 -2
  279. data/lib/graphql/version.rb +1 -1
  280. data/lib/graphql.rb +41 -58
  281. data/readme.md +3 -6
  282. metadata +97 -231
  283. data/lib/graphql/analysis/analyze_query.rb +0 -91
  284. data/lib/graphql/analysis/field_usage.rb +0 -45
  285. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  286. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  287. data/lib/graphql/analysis/query_complexity.rb +0 -88
  288. data/lib/graphql/analysis/query_depth.rb +0 -43
  289. data/lib/graphql/analysis/reducer_state.rb +0 -48
  290. data/lib/graphql/argument.rb +0 -159
  291. data/lib/graphql/authorization.rb +0 -82
  292. data/lib/graphql/backwards_compatibility.rb +0 -60
  293. data/lib/graphql/base_type.rb +0 -226
  294. data/lib/graphql/boolean_type.rb +0 -2
  295. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  296. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  297. data/lib/graphql/compatibility/execution_specification.rb +0 -435
  298. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  299. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -213
  300. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -91
  301. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  302. data/lib/graphql/compatibility/query_parser_specification.rb +0 -264
  303. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -680
  304. data/lib/graphql/compatibility.rb +0 -5
  305. data/lib/graphql/define/assign_argument.rb +0 -12
  306. data/lib/graphql/define/assign_connection.rb +0 -13
  307. data/lib/graphql/define/assign_enum_value.rb +0 -18
  308. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  309. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  310. data/lib/graphql/define/assign_object_field.rb +0 -42
  311. data/lib/graphql/define/defined_object_proxy.rb +0 -53
  312. data/lib/graphql/define/instance_definable.rb +0 -311
  313. data/lib/graphql/define/no_definition_error.rb +0 -7
  314. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  315. data/lib/graphql/define/type_definer.rb +0 -31
  316. data/lib/graphql/define.rb +0 -31
  317. data/lib/graphql/deprecated_dsl.rb +0 -42
  318. data/lib/graphql/directive/deprecated_directive.rb +0 -13
  319. data/lib/graphql/directive/include_directive.rb +0 -2
  320. data/lib/graphql/directive/skip_directive.rb +0 -2
  321. data/lib/graphql/directive.rb +0 -104
  322. data/lib/graphql/enum_type.rb +0 -193
  323. data/lib/graphql/execution/execute.rb +0 -326
  324. data/lib/graphql/execution/flatten.rb +0 -40
  325. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  326. data/lib/graphql/execution/typecast.rb +0 -50
  327. data/lib/graphql/field/resolve.rb +0 -59
  328. data/lib/graphql/field.rb +0 -330
  329. data/lib/graphql/float_type.rb +0 -2
  330. data/lib/graphql/function.rb +0 -153
  331. data/lib/graphql/id_type.rb +0 -2
  332. data/lib/graphql/input_object_type.rb +0 -154
  333. data/lib/graphql/int_type.rb +0 -2
  334. data/lib/graphql/interface_type.rb +0 -86
  335. data/lib/graphql/internal_representation/document.rb +0 -27
  336. data/lib/graphql/internal_representation/node.rb +0 -206
  337. data/lib/graphql/internal_representation/print.rb +0 -51
  338. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  339. data/lib/graphql/internal_representation/scope.rb +0 -88
  340. data/lib/graphql/internal_representation/visit.rb +0 -36
  341. data/lib/graphql/internal_representation.rb +0 -7
  342. data/lib/graphql/list_type.rb +0 -80
  343. data/lib/graphql/literal_validation_error.rb +0 -6
  344. data/lib/graphql/non_null_type.rb +0 -81
  345. data/lib/graphql/object_type.rb +0 -141
  346. data/lib/graphql/query/arguments.rb +0 -187
  347. data/lib/graphql/query/arguments_cache.rb +0 -25
  348. data/lib/graphql/query/executor.rb +0 -53
  349. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  350. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  351. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  352. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  353. data/lib/graphql/query/serial_execution.rb +0 -39
  354. data/lib/graphql/relay/array_connection.rb +0 -85
  355. data/lib/graphql/relay/base_connection.rb +0 -172
  356. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  357. data/lib/graphql/relay/connection_resolve.rb +0 -43
  358. data/lib/graphql/relay/connection_type.rb +0 -40
  359. data/lib/graphql/relay/edge.rb +0 -27
  360. data/lib/graphql/relay/edge_type.rb +0 -18
  361. data/lib/graphql/relay/edges_instrumentation.rb +0 -40
  362. data/lib/graphql/relay/global_id_resolve.rb +0 -18
  363. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  364. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  365. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  366. data/lib/graphql/relay/mutation/result.rb +0 -38
  367. data/lib/graphql/relay/mutation.rb +0 -190
  368. data/lib/graphql/relay/node.rb +0 -36
  369. data/lib/graphql/relay/page_info.rb +0 -7
  370. data/lib/graphql/relay/relation_connection.rb +0 -190
  371. data/lib/graphql/relay/type_extensions.rb +0 -30
  372. data/lib/graphql/scalar_type.rb +0 -133
  373. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  374. data/lib/graphql/schema/default_parse_error.rb +0 -10
  375. data/lib/graphql/schema/default_type_error.rb +0 -15
  376. data/lib/graphql/schema/member/accepts_definition.rb +0 -152
  377. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -26
  378. data/lib/graphql/schema/member/instrumentation.rb +0 -132
  379. data/lib/graphql/schema/middleware_chain.rb +0 -82
  380. data/lib/graphql/schema/possible_types.rb +0 -39
  381. data/lib/graphql/schema/rescue_middleware.rb +0 -60
  382. data/lib/graphql/schema/timeout_middleware.rb +0 -86
  383. data/lib/graphql/schema/traversal.rb +0 -228
  384. data/lib/graphql/schema/validation.rb +0 -303
  385. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  386. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  387. data/lib/graphql/string_type.rb +0 -2
  388. data/lib/graphql/subscriptions/subscription_root.rb +0 -74
  389. data/lib/graphql/tracing/skylight_tracing.rb +0 -62
  390. data/lib/graphql/types/relay/base_field.rb +0 -22
  391. data/lib/graphql/types/relay/base_interface.rb +0 -29
  392. data/lib/graphql/types/relay/base_object.rb +0 -26
  393. data/lib/graphql/types/relay/node_field.rb +0 -43
  394. data/lib/graphql/types/relay/nodes_field.rb +0 -45
  395. data/lib/graphql/union_type.rb +0 -135
  396. data/lib/graphql/upgrader/member.rb +0 -936
  397. data/lib/graphql/upgrader/schema.rb +0 -37
@@ -4,37 +4,32 @@ module GraphQL
4
4
  # Used to convert your {GraphQL::Schema} to a GraphQL schema string
5
5
  #
6
6
  # @example print your schema to standard output (via helper)
7
- # MySchema = GraphQL::Schema.define(query: QueryType)
8
7
  # puts GraphQL::Schema::Printer.print_schema(MySchema)
9
8
  #
10
9
  # @example print your schema to standard output
11
- # MySchema = GraphQL::Schema.define(query: QueryType)
12
10
  # puts GraphQL::Schema::Printer.new(MySchema).print_schema
13
11
  #
14
12
  # @example print a single type to standard output
15
- # query_root = GraphQL::ObjectType.define do
16
- # name "Query"
13
+ # class Types::Query < GraphQL::Schema::Object
17
14
  # description "The query root of this schema"
18
15
  #
19
- # field :post do
20
- # type post_type
21
- # resolve ->(obj, args, ctx) { Post.find(args["id"]) }
22
- # end
16
+ # field :post, Types::Post, null: true
23
17
  # end
24
18
  #
25
- # post_type = GraphQL::ObjectType.define do
26
- # name "Post"
19
+ # class Types::Post < GraphQL::Schema::Object
27
20
  # description "A blog post"
28
21
  #
29
- # field :id, !types.ID
30
- # field :title, !types.String
31
- # field :body, !types.String
22
+ # field :id, ID, null: false
23
+ # field :title, String, null: false
24
+ # field :body, String, null: false
32
25
  # end
33
26
  #
34
- # MySchema = GraphQL::Schema.define(query: query_root)
27
+ # class MySchema < GraphQL::Schema
28
+ # query(Types::Query)
29
+ # end
35
30
  #
36
31
  # printer = GraphQL::Schema::Printer.new(MySchema)
37
- # puts printer.print_type(post_type)
32
+ # puts printer.print_type(Types::Post)
38
33
  #
39
34
  class Printer < GraphQL::Language::Printer
40
35
  attr_reader :schema, :warden
@@ -54,20 +49,20 @@ module GraphQL
54
49
  )
55
50
 
56
51
  @document = @document_from_schema.document
57
-
58
52
  @schema = schema
59
53
  end
60
54
 
61
55
  # Return the GraphQL schema string for the introspection type system
62
56
  def self.print_introspection_schema
63
- query_root = ObjectType.define(name: "Root") do
64
- field :throwaway_field, types.String
57
+ query_root = Class.new(GraphQL::Schema::Object) do
58
+ graphql_name "Root"
59
+ field :throwaway_field, String
65
60
  end
66
- schema = GraphQL::Schema.define(query: query_root)
61
+ schema = Class.new(GraphQL::Schema) { query(query_root) }
67
62
 
68
63
  introspection_schema_ast = GraphQL::Language::DocumentFromSchemaDefinition.new(
69
64
  schema,
70
- except: ->(member, _) { member.name == "Root" },
65
+ except: ->(member, _) { member.graphql_name == "Root" },
71
66
  include_introspection_types: true,
72
67
  include_built_in_directives: true,
73
68
  ).document
@@ -87,7 +82,7 @@ module GraphQL
87
82
 
88
83
  # Return a GraphQL schema string for the defined types in the schema
89
84
  def print_schema
90
- print(@document)
85
+ print(@document) + "\n"
91
86
  end
92
87
 
93
88
  def print_type(type)
@@ -95,20 +90,6 @@ module GraphQL
95
90
  print(node)
96
91
  end
97
92
 
98
- def print_directive(directive)
99
- if directive.name == "deprecated"
100
- reason = directive.arguments.find { |arg| arg.name == "reason" }
101
-
102
- if reason.value == GraphQL::Directive::DEFAULT_DEPRECATION_REASON
103
- "@deprecated"
104
- else
105
- "@deprecated(reason: #{reason.value.to_s.inspect})"
106
- end
107
- else
108
- super
109
- end
110
- end
111
-
112
93
  class IntrospectionPrinter < GraphQL::Language::Printer
113
94
  def print_schema_definition(schema)
114
95
  "schema {\n query: Root\n}"
@@ -22,32 +22,26 @@ module GraphQL
22
22
  #
23
23
  class RelayClassicMutation < GraphQL::Schema::Mutation
24
24
  # The payload should always include this field
25
- field(:client_mutation_id, String, "A unique identifier for the client performing the mutation.", null: true)
25
+ field(:client_mutation_id, String, "A unique identifier for the client performing the mutation.")
26
26
  # Relay classic default:
27
27
  null(true)
28
28
 
29
29
  # Override {GraphQL::Schema::Resolver#resolve_with_support} to
30
30
  # delete `client_mutation_id` from the kwargs.
31
31
  def resolve_with_support(**inputs)
32
- # Without the interpreter, the inputs are unwrapped by an instrumenter.
33
- # But when using the interpreter, no instrumenters are applied.
34
- if context.interpreter?
35
- input = inputs[:input].to_kwargs
36
-
37
- new_extras = field ? field.extras : []
38
- all_extras = self.class.extras + new_extras
39
-
40
- # Transfer these from the top-level hash to the
41
- # shortcutted `input:` object
42
- all_extras.each do |ext|
43
- # It's possible that the `extra` was not passed along by this point,
44
- # don't re-add it if it wasn't given here.
45
- if inputs.key?(ext)
46
- input[ext] = inputs[ext]
47
- end
32
+ input = inputs[:input].to_kwargs
33
+
34
+ new_extras = field ? field.extras : []
35
+ all_extras = self.class.extras + new_extras
36
+
37
+ # Transfer these from the top-level hash to the
38
+ # shortcutted `input:` object
39
+ all_extras.each do |ext|
40
+ # It's possible that the `extra` was not passed along by this point,
41
+ # don't re-add it if it wasn't given here.
42
+ if inputs.key?(ext)
43
+ input[ext] = inputs[ext]
48
44
  end
49
- else
50
- input = inputs
51
45
  end
52
46
 
53
47
  if input
@@ -66,21 +60,41 @@ module GraphQL
66
60
  super()
67
61
  end
68
62
 
69
- # Again, this is done by an instrumenter when using non-interpreter execution.
70
- if context.interpreter?
71
- context.schema.after_lazy(return_value) do |return_hash|
72
- # It might be an error
73
- if return_hash.is_a?(Hash)
74
- return_hash[:client_mutation_id] = client_mutation_id
75
- end
76
- return_hash
63
+ context.schema.after_lazy(return_value) do |return_hash|
64
+ # It might be an error
65
+ if return_hash.is_a?(Hash)
66
+ return_hash[:client_mutation_id] = client_mutation_id
77
67
  end
78
- else
79
- return_value
68
+ return_hash
80
69
  end
81
70
  end
82
71
 
83
72
  class << self
73
+
74
+ # Also apply this argument to the input type:
75
+ def argument(*args, **kwargs, &block)
76
+ it = input_type # make sure any inherited arguments are already added to it
77
+ arg = super
78
+
79
+ # This definition might be overriding something inherited;
80
+ # if it is, remove the inherited definition so it's not confused at runtime as having multiple definitions
81
+ prev_args = it.own_arguments[arg.graphql_name]
82
+ case prev_args
83
+ when GraphQL::Schema::Argument
84
+ if prev_args.owner != self
85
+ it.own_arguments.delete(arg.graphql_name)
86
+ end
87
+ when Array
88
+ prev_args.reject! { |a| a.owner != self }
89
+ if prev_args.empty?
90
+ it.own_arguments.delete(arg.graphql_name)
91
+ end
92
+ end
93
+
94
+ it.add_argument(arg)
95
+ arg
96
+ end
97
+
84
98
  # The base class for generated input object types
85
99
  # @param new_class [Class] The base class to use for generating input object definitions
86
100
  # @return [Class] The base class for this mutation's generated input object (default is {GraphQL::Schema::InputObject})
@@ -105,7 +119,7 @@ module GraphQL
105
119
  sig = super
106
120
  # Arguments were added at the root, but they should be nested
107
121
  sig[:arguments].clear
108
- sig[:arguments][:input] = { type: input_type, required: true }
122
+ sig[:arguments][:input] = { type: input_type, required: true, description: "Parameters for #{graphql_name}" }
109
123
  sig
110
124
  end
111
125
 
@@ -115,18 +129,29 @@ module GraphQL
115
129
  # To customize how input objects are generated, override this method
116
130
  # @return [Class] a subclass of {.input_object_class}
117
131
  def generate_input_type
118
- mutation_args = arguments
132
+ mutation_args = all_argument_definitions
119
133
  mutation_name = graphql_name
120
134
  mutation_class = self
121
135
  Class.new(input_object_class) do
122
136
  graphql_name("#{mutation_name}Input")
123
137
  description("Autogenerated input type of #{mutation_name}")
124
138
  mutation(mutation_class)
125
- own_arguments.merge!(mutation_args)
139
+ # these might be inherited:
140
+ mutation_args.each do |arg|
141
+ add_argument(arg)
142
+ end
126
143
  argument :client_mutation_id, String, "A unique identifier for the client performing the mutation.", required: false
127
144
  end
128
145
  end
129
146
  end
147
+
148
+ private
149
+
150
+ def authorize_arguments(args, values)
151
+ # remove the `input` wrapper to match values
152
+ input_args = args["input"].type.unwrap.arguments(context)
153
+ super(input_args, values)
154
+ end
130
155
  end
131
156
  end
132
157
  end
@@ -26,8 +26,10 @@ module GraphQL
26
26
  def field_class(new_class = nil)
27
27
  if new_class
28
28
  @field_class = new_class
29
+ elsif defined?(@field_class) && @field_class
30
+ @field_class
29
31
  else
30
- @field_class || find_inherited_value(:field_class, GraphQL::Schema::Field)
32
+ find_inherited_value(:field_class, GraphQL::Schema::Field)
31
33
  end
32
34
  end
33
35
 
@@ -36,12 +38,39 @@ module GraphQL
36
38
  # @return [Class]
37
39
  def object_class(new_class = nil)
38
40
  if new_class
41
+ if defined?(@payload_type)
42
+ raise "Can't configure `object_class(...)` after the payload type has already been initialized. Move this configuration higher up the class definition."
43
+ end
39
44
  @object_class = new_class
40
45
  else
41
46
  @object_class || find_inherited_value(:object_class, GraphQL::Schema::Object)
42
47
  end
43
48
  end
44
49
 
50
+ NO_INTERFACES = [].freeze
51
+
52
+ def field(*args, **kwargs, &block)
53
+ pt = payload_type # make sure it's initialized with any inherited fields
54
+ field_defn = super
55
+
56
+ # Remove any inherited fields to avoid false conflicts at runtime
57
+ prev_fields = pt.own_fields[field_defn.graphql_name]
58
+ case prev_fields
59
+ when GraphQL::Schema::Field
60
+ if prev_fields.owner != self
61
+ pt.own_fields.delete(field_defn.graphql_name)
62
+ end
63
+ when Array
64
+ prev_fields.reject! { |f| f.owner != self }
65
+ if prev_fields.empty?
66
+ pt.own_fields.delete(field_defn.graphql_name)
67
+ end
68
+ end
69
+
70
+ pt.add_field(field_defn, method_conflict_warning: false)
71
+ field_defn
72
+ end
73
+
45
74
  private
46
75
 
47
76
  # Build a subclass of {.object_class} based on `self`.
@@ -49,14 +78,15 @@ module GraphQL
49
78
  # Override this hook to customize return type generation.
50
79
  def generate_payload_type
51
80
  resolver_name = graphql_name
52
- resolver_fields = fields
81
+ resolver_fields = all_field_definitions
53
82
  Class.new(object_class) do
54
83
  graphql_name("#{resolver_name}Payload")
55
84
  description("Autogenerated return type of #{resolver_name}")
56
- resolver_fields.each do |name, f|
85
+ resolver_fields.each do |f|
57
86
  # Reattach the already-defined field here
58
87
  # (The field's `.owner` will still point to the mutation, not the object type, I think)
59
- add_field(f)
88
+ # Don't re-warn about a method conflict. Since this type is generated, it should be fixed in the resolver instead.
89
+ add_field(f, method_conflict_warning: false)
60
90
  end
61
91
  end
62
92
  end
@@ -24,10 +24,11 @@ module GraphQL
24
24
  # Really we only need description from here, but:
25
25
  extend Schema::Member::BaseDSLMethods
26
26
  extend GraphQL::Schema::Member::HasArguments
27
+ extend GraphQL::Schema::Member::HasValidators
27
28
  include Schema::Member::HasPath
28
29
  extend Schema::Member::HasPath
29
30
 
30
- # @param object [Object] the initialize object, pass to {Query.initialize} as `root_value`
31
+ # @param object [Object] The application object that this field is being resolved on
31
32
  # @param context [GraphQL::Query::Context]
32
33
  # @param field [GraphQL::Schema::Field]
33
34
  def initialize(object:, context:, field:)
@@ -36,10 +37,10 @@ module GraphQL
36
37
  @field = field
37
38
  # Since this hash is constantly rebuilt, cache it for this call
38
39
  @arguments_by_keyword = {}
39
- self.class.arguments.each do |name, arg|
40
+ self.class.arguments(context).each do |name, arg|
40
41
  @arguments_by_keyword[arg.keyword] = arg
41
42
  end
42
- @arguments_loads_as_type = self.class.arguments_loads_as_type
43
+ @prepared_arguments = nil
43
44
  end
44
45
 
45
46
  # @return [Object] The application object this field is being resolved on
@@ -48,9 +49,18 @@ module GraphQL
48
49
  # @return [GraphQL::Query::Context]
49
50
  attr_reader :context
50
51
 
52
+ # @return [GraphQL::Dataloader]
53
+ def dataloader
54
+ context.dataloader
55
+ end
56
+
51
57
  # @return [GraphQL::Schema::Field]
52
58
  attr_reader :field
53
59
 
60
+ def arguments
61
+ @prepared_arguments || raise("Arguments have not been prepared yet, still waiting for #load_arguments to resolve. (Call `.arguments` later in the code.)")
62
+ end
63
+
54
64
  # This method is _actually_ called by the runtime,
55
65
  # it does some preparation and then eventually calls
56
66
  # the user-defined `#resolve` method.
@@ -74,6 +84,8 @@ module GraphQL
74
84
  # for that argument, or may return a lazy object
75
85
  load_arguments_val = load_arguments(args)
76
86
  context.schema.after_lazy(load_arguments_val) do |loaded_args|
87
+ @prepared_arguments = loaded_args
88
+ Schema::Validator.validate!(self.class.validators, object, context, loaded_args, as: @field)
77
89
  # Then call `authorized?`, which may raise or may return a lazy object
78
90
  authorized_val = if loaded_args.any?
79
91
  authorized?(**loaded_args)
@@ -97,7 +109,7 @@ module GraphQL
97
109
  public_send(self.class.resolve_method)
98
110
  end
99
111
  else
100
- nil
112
+ raise GraphQL::UnauthorizedFieldError.new(context: context, object: object, type: field.owner, field: field)
101
113
  end
102
114
  end
103
115
  end
@@ -133,22 +145,28 @@ module GraphQL
133
145
  # @raise [GraphQL::UnauthorizedError] To signal an authorization failure
134
146
  # @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
135
147
  def authorized?(**inputs)
136
- self.class.arguments.each_value do |argument|
137
- arg_keyword = argument.keyword
138
- if inputs.key?(arg_keyword) && !(value = inputs[arg_keyword]).nil? && (value != argument.default_value)
139
- loads_type = @arguments_loads_as_type[arg_keyword]
140
- # If this argument resulted in an object being loaded,
141
- # then authorize this loaded object with its own policy.
142
- #
143
- # But if this argument was "just" a plain argument, like
144
- # a boolean, then authorize it based on the mutation.
145
- authorization_value = if loads_type
146
- value
147
- else
148
- self
149
- end
148
+ arg_owner = @field # || self.class
149
+ args = arg_owner.arguments(context)
150
+ authorize_arguments(args, inputs)
151
+ end
150
152
 
151
- arg_auth, err = argument.authorized?(authorization_value, context)
153
+ # Called when an object loaded by `loads:` fails the `.authorized?` check for its resolved GraphQL object type.
154
+ #
155
+ # By default, the error is re-raised and passed along to {{Schema.unauthorized_object}}.
156
+ #
157
+ # Any value returned here will be used _instead of_ of the loaded object.
158
+ # @param err [GraphQL::UnauthorizedError]
159
+ def unauthorized_object(err)
160
+ raise err
161
+ end
162
+
163
+ private
164
+
165
+ def authorize_arguments(args, inputs)
166
+ args.each_value do |argument|
167
+ arg_keyword = argument.keyword
168
+ if inputs.key?(arg_keyword) && !(arg_value = inputs[arg_keyword]).nil? && (arg_value != argument.default_value)
169
+ arg_auth, err = argument.authorized?(self, arg_value, context)
152
170
  if !arg_auth
153
171
  return arg_auth, err
154
172
  else
@@ -160,8 +178,6 @@ module GraphQL
160
178
  end
161
179
  end
162
180
 
163
- private
164
-
165
181
  def load_arguments(args)
166
182
  prepared_args = {}
167
183
  prepare_lazies = []
@@ -169,18 +185,14 @@ module GraphQL
169
185
  args.each do |key, value|
170
186
  arg_defn = @arguments_by_keyword[key]
171
187
  if arg_defn
172
- if value.nil?
173
- prepared_args[key] = value
174
- else
175
- prepped_value = prepared_args[key] = load_argument(key, value)
176
- if context.schema.lazy?(prepped_value)
177
- prepare_lazies << context.schema.after_lazy(prepped_value) do |finished_prepped_value|
178
- prepared_args[key] = finished_prepped_value
179
- end
188
+ prepped_value = prepared_args[key] = arg_defn.load_and_authorize_value(self, value, context)
189
+ if context.schema.lazy?(prepped_value)
190
+ prepare_lazies << context.schema.after_lazy(prepped_value) do |finished_prepped_value|
191
+ prepared_args[key] = finished_prepped_value
180
192
  end
181
193
  end
182
194
  else
183
- # These are `extras: [...]`
195
+ # these are `extras:`
184
196
  prepared_args[key] = value
185
197
  end
186
198
  end
@@ -193,8 +205,8 @@ module GraphQL
193
205
  end
194
206
  end
195
207
 
196
- def load_argument(name, value)
197
- public_send("load_#{name}", value)
208
+ def get_argument(name, context = GraphQL::Query::NullContext)
209
+ self.class.get_argument(name, context)
198
210
  end
199
211
 
200
212
  class << self
@@ -217,8 +229,10 @@ module GraphQL
217
229
  own_extras + (superclass.respond_to?(:extras) ? superclass.extras : [])
218
230
  end
219
231
 
220
- # Specifies whether or not the field is nullable. Defaults to `true`
221
- # TODO unify with {#type}
232
+ # If `true` (default), then the return type for this resolver will be nullable.
233
+ # If `false`, then the return type is non-null.
234
+ #
235
+ # @see #type which sets the return type of this field and accepts a `null:` option
222
236
  # @param allow_null [Boolean] Whether or not the response can be null
223
237
  def null(allow_null = nil)
224
238
  if !allow_null.nil?
@@ -232,7 +246,7 @@ module GraphQL
232
246
  # or use it as a configuration method to assign a return type
233
247
  # instead of generating one.
234
248
  # TODO unify with {#null}
235
- # @param new_type [Class, nil] If a type definition class is provided, it will be used as the return type of the field
249
+ # @param new_type [Class, Array<Class>, nil] If a type definition class is provided, it will be used as the return type of the field
236
250
  # @param null [true, false] Whether or not the field may return `nil`
237
251
  # @return [Class] The type which this field returns.
238
252
  def type(new_type = nil, null: nil)
@@ -262,18 +276,78 @@ module GraphQL
262
276
  @complexity || (superclass.respond_to?(:complexity) ? superclass.complexity : 1)
263
277
  end
264
278
 
279
+ def broadcastable(new_broadcastable)
280
+ @broadcastable = new_broadcastable
281
+ end
282
+
283
+ # @return [Boolean, nil]
284
+ def broadcastable?
285
+ if defined?(@broadcastable)
286
+ @broadcastable
287
+ else
288
+ (superclass.respond_to?(:broadcastable?) ? superclass.broadcastable? : nil)
289
+ end
290
+ end
291
+
292
+ # Get or set the `max_page_size:` which will be configured for fields using this resolver
293
+ # (`nil` means "unlimited max page size".)
294
+ # @param max_page_size [Integer, nil] Set a new value
295
+ # @return [Integer, nil] The `max_page_size` assigned to fields that use this resolver
296
+ def max_page_size(new_max_page_size = :not_given)
297
+ if new_max_page_size != :not_given
298
+ @max_page_size = new_max_page_size
299
+ elsif defined?(@max_page_size)
300
+ @max_page_size
301
+ elsif superclass.respond_to?(:max_page_size)
302
+ superclass.max_page_size
303
+ else
304
+ nil
305
+ end
306
+ end
307
+
308
+ # @return [Boolean] `true` if this resolver or a superclass has an assigned `max_page_size`
309
+ def has_max_page_size?
310
+ defined?(@max_page_size) || (superclass.respond_to?(:has_max_page_size?) && superclass.has_max_page_size?)
311
+ end
312
+
265
313
  def field_options
266
- {
314
+
315
+ all_args = {}
316
+ all_argument_definitions.each do |arg|
317
+ if (prev_entry = all_args[arg.graphql_name])
318
+ if prev_entry.is_a?(Array)
319
+ prev_entry << arg
320
+ else
321
+ all_args[arg.graphql_name] = [prev_entry, arg]
322
+ end
323
+ else
324
+ all_args[arg.graphql_name] = arg
325
+ end
326
+ end
327
+
328
+ field_opts = {
267
329
  type: type_expr,
268
330
  description: description,
269
331
  extras: extras,
270
332
  resolver_method: :resolve_with_support,
271
333
  resolver_class: self,
272
- arguments: arguments,
334
+ arguments: all_args,
273
335
  null: null,
274
336
  complexity: complexity,
275
- extensions: extensions,
337
+ broadcastable: broadcastable?,
276
338
  }
339
+
340
+ # If there aren't any, then the returned array is `[].freeze`,
341
+ # but passing that along breaks some user code.
342
+ if (exts = extensions).any?
343
+ field_opts[:extensions] = exts
344
+ end
345
+
346
+ if has_max_page_size?
347
+ field_opts[:max_page_size] = max_page_size
348
+ end
349
+
350
+ field_opts
277
351
  end
278
352
 
279
353
  # A non-normalized type configuration, without `null` applied
@@ -285,63 +359,43 @@ module GraphQL
285
359
  # also add some preparation hook methods which will be used for this argument
286
360
  # @see {GraphQL::Schema::Argument#initialize} for the signature
287
361
  def argument(*args, **kwargs, &block)
288
- loads = kwargs[:loads]
289
362
  # Use `from_resolver: true` to short-circuit the InputObject's own `loads:` implementation
290
363
  # so that we can support `#load_{x}` methods below.
291
- arg_defn = super(*args, from_resolver: true, **kwargs)
292
- own_arguments_loads_as_type[arg_defn.keyword] = loads if loads
293
-
294
- if loads && arg_defn.type.list?
295
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
296
- def load_#{arg_defn.keyword}(values)
297
- argument = @arguments_by_keyword[:#{arg_defn.keyword}]
298
- lookup_as_type = @arguments_loads_as_type[:#{arg_defn.keyword}]
299
- context.schema.after_lazy(values) do |values2|
300
- GraphQL::Execution::Lazy.all(values2.map { |value| load_application_object(argument, lookup_as_type, value) })
301
- end
302
- end
303
- RUBY
304
- elsif loads
305
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
306
- def load_#{arg_defn.keyword}(value)
307
- argument = @arguments_by_keyword[:#{arg_defn.keyword}]
308
- lookup_as_type = @arguments_loads_as_type[:#{arg_defn.keyword}]
309
- load_application_object(argument, lookup_as_type, value)
310
- end
311
- RUBY
312
- else
313
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
314
- def load_#{arg_defn.keyword}(value)
315
- value
316
- end
317
- RUBY
318
- end
319
-
320
- arg_defn
321
- end
322
-
323
- # @api private
324
- def arguments_loads_as_type
325
- inherited_lookups = superclass.respond_to?(:arguments_loads_as_type) ? superclass.arguments_loads_as_type : {}
326
- inherited_lookups.merge(own_arguments_loads_as_type)
364
+ super(*args, from_resolver: true, **kwargs)
327
365
  end
328
366
 
329
367
  # Registers new extension
330
368
  # @param extension [Class] Extension class
331
369
  # @param options [Hash] Optional extension options
332
370
  def extension(extension, **options)
333
- extensions << {extension => options}
371
+ @own_extensions ||= []
372
+ @own_extensions << {extension => options}
334
373
  end
335
374
 
336
375
  # @api private
337
376
  def extensions
338
- @extensions ||= []
377
+ own_exts = @own_extensions
378
+ # Jump through some hoops to avoid creating arrays when we don't actually need them
379
+ if superclass.respond_to?(:extensions)
380
+ s_exts = superclass.extensions
381
+ if own_exts
382
+ if s_exts.any?
383
+ own_exts + s_exts
384
+ else
385
+ own_exts
386
+ end
387
+ else
388
+ s_exts
389
+ end
390
+ else
391
+ own_exts || EMPTY_ARRAY
392
+ end
339
393
  end
340
394
 
341
395
  private
342
396
 
343
- def own_arguments_loads_as_type
344
- @own_arguments_loads_as_type ||= {}
397
+ def own_extensions
398
+ @own_extensions
345
399
  end
346
400
  end
347
401
  end