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
@@ -0,0 +1,240 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Addition
6
+ attr_reader :directives, :possible_types, :types, :union_memberships, :references, :arguments_with_default_values
7
+
8
+ def initialize(schema:, own_types:, new_types:)
9
+ @schema = schema
10
+ @own_types = own_types
11
+ @directives = Set.new
12
+ @possible_types = {}
13
+ @types = {}
14
+ @union_memberships = {}
15
+ @references = Hash.new { |h, k| h[k] = [] }
16
+ @arguments_with_default_values = []
17
+ add_type_and_traverse(new_types)
18
+ end
19
+
20
+ private
21
+
22
+ def references_to(thing, from:)
23
+ @references[thing] << from
24
+ end
25
+
26
+ def get_type(name)
27
+ local_type = @types[name]
28
+ # This isn't really sophisticated, but
29
+ # I think it's good enough to support the current usage of LateBoundTypes
30
+ if local_type.is_a?(Array)
31
+ local_type = local_type.first
32
+ end
33
+ local_type || @schema.get_type(name)
34
+ end
35
+
36
+ # Lookup using `own_types` here because it's ok to override
37
+ # inherited types by name
38
+ def get_local_type(name)
39
+ @types[name] || @own_types[name]
40
+ end
41
+
42
+ def add_directives_from(owner)
43
+ dirs = owner.directives.map(&:class)
44
+ @directives.merge(dirs)
45
+ add_type_and_traverse(dirs)
46
+ end
47
+
48
+ def add_type_and_traverse(new_types)
49
+ late_types = []
50
+ new_types.each { |t| add_type(t, owner: nil, late_types: late_types, path: [t.graphql_name]) }
51
+ missed_late_types = 0
52
+ while (late_type_vals = late_types.shift)
53
+ type_owner, lt = late_type_vals
54
+ if lt.is_a?(String)
55
+ type = Member::BuildType.constantize(lt)
56
+ # Reset the counter, since we might succeed next go-round
57
+ missed_late_types = 0
58
+ update_type_owner(type_owner, type)
59
+ add_type(type, owner: type_owner, late_types: late_types, path: [type.graphql_name])
60
+ elsif lt.is_a?(LateBoundType)
61
+ if (type = get_type(lt.name))
62
+ # Reset the counter, since we might succeed next go-round
63
+ missed_late_types = 0
64
+ update_type_owner(type_owner, type)
65
+ add_type(type, owner: type_owner, late_types: late_types, path: [type.graphql_name])
66
+ else
67
+ missed_late_types += 1
68
+ # Add it back to the list, maybe we'll be able to resolve it later.
69
+ late_types << [type_owner, lt]
70
+ if missed_late_types == late_types.size
71
+ # We've looked at all of them and haven't resolved one.
72
+ raise UnresolvedLateBoundTypeError.new(type: lt)
73
+ else
74
+ # Try the next one
75
+ end
76
+ end
77
+ else
78
+ raise ArgumentError, "Unexpected late type: #{lt.inspect}"
79
+ end
80
+ end
81
+ nil
82
+ end
83
+
84
+ def update_type_owner(owner, type)
85
+ case owner
86
+ when Module
87
+ if owner.kind.union?
88
+ # It's a union with possible_types
89
+ # Replace the item by class name
90
+ owner.assign_type_membership_object_type(type)
91
+ @possible_types[owner.graphql_name] = owner.possible_types
92
+ elsif type.kind.interface? && (owner.kind.object? || owner.kind.interface?)
93
+ new_interfaces = []
94
+ owner.interfaces.each do |int_t|
95
+ if int_t.is_a?(String) && int_t == type.graphql_name
96
+ new_interfaces << type
97
+ elsif int_t.is_a?(LateBoundType) && int_t.graphql_name == type.graphql_name
98
+ new_interfaces << type
99
+ else
100
+ # Don't re-add proper interface definitions,
101
+ # they were probably already added, maybe with options.
102
+ end
103
+ end
104
+ owner.implements(*new_interfaces)
105
+ new_interfaces.each do |int|
106
+ pt = @possible_types[int.graphql_name] ||= []
107
+ if !pt.include?(owner) && owner.is_a?(Class)
108
+ pt << owner
109
+ end
110
+ end
111
+ end
112
+ when nil
113
+ # It's a root type
114
+ @types[type.graphql_name] = type
115
+ when GraphQL::Schema::Field, GraphQL::Schema::Argument
116
+ orig_type = owner.type
117
+ # Apply list/non-null wrapper as needed
118
+ if orig_type.respond_to?(:of_type)
119
+ transforms = []
120
+ while (orig_type.respond_to?(:of_type))
121
+ if orig_type.kind.non_null?
122
+ transforms << :to_non_null_type
123
+ elsif orig_type.kind.list?
124
+ transforms << :to_list_type
125
+ else
126
+ raise "Invariant: :of_type isn't non-null or list"
127
+ end
128
+ orig_type = orig_type.of_type
129
+ end
130
+ transforms.reverse_each { |t| type = type.public_send(t) }
131
+ end
132
+ owner.type = type
133
+ else
134
+ raise "Unexpected update: #{owner.inspect} #{type.inspect}"
135
+ end
136
+ end
137
+
138
+ def add_type(type, owner:, late_types:, path:)
139
+ if type.is_a?(String) || type.is_a?(GraphQL::Schema::LateBoundType)
140
+ late_types << [owner, type]
141
+ return
142
+ end
143
+
144
+ if owner.is_a?(Class) && owner < GraphQL::Schema::Union
145
+ um = @union_memberships[type.graphql_name] ||= []
146
+ um << owner
147
+ end
148
+
149
+ if (prev_type = get_local_type(type.graphql_name)) && prev_type == type
150
+ # No need to re-visit
151
+ elsif type.is_a?(Class) && type < GraphQL::Schema::Directive
152
+ @directives << type
153
+ type.all_argument_definitions.each do |arg|
154
+ arg_type = arg.type.unwrap
155
+ references_to(arg_type, from: arg)
156
+ add_type(arg_type, owner: arg, late_types: late_types, path: path + [arg.graphql_name])
157
+ if arg.default_value?
158
+ @arguments_with_default_values << arg
159
+ end
160
+ end
161
+ else
162
+ prev_type = @types[type.graphql_name]
163
+ if prev_type.nil?
164
+ @types[type.graphql_name] = type
165
+ elsif prev_type.is_a?(Array)
166
+ prev_type << type
167
+ else
168
+ @types[type.graphql_name] = [prev_type, type]
169
+ end
170
+
171
+ add_directives_from(type)
172
+ if type.kind.fields?
173
+ type.all_field_definitions.each do |field|
174
+ name = field.graphql_name
175
+ field_type = field.type.unwrap
176
+ references_to(field_type, from: field)
177
+ field_path = path + [name]
178
+ add_type(field_type, owner: field, late_types: late_types, path: field_path)
179
+ add_directives_from(field)
180
+ field.all_argument_definitions.each do |arg|
181
+ add_directives_from(arg)
182
+ arg_type = arg.type.unwrap
183
+ references_to(arg_type, from: arg)
184
+ add_type(arg_type, owner: arg, late_types: late_types, path: field_path + [arg.graphql_name])
185
+ if arg.default_value?
186
+ @arguments_with_default_values << arg
187
+ end
188
+ end
189
+ end
190
+ end
191
+ if type.kind.input_object?
192
+ type.all_argument_definitions.each do |arg|
193
+ add_directives_from(arg)
194
+ arg_type = arg.type.unwrap
195
+ references_to(arg_type, from: arg)
196
+ add_type(arg_type, owner: arg, late_types: late_types, path: path + [arg.graphql_name])
197
+ if arg.default_value?
198
+ @arguments_with_default_values << arg
199
+ end
200
+ end
201
+ end
202
+ if type.kind.union?
203
+ @possible_types[type.graphql_name] = type.all_possible_types
204
+ type.all_possible_types.each do |t|
205
+ add_type(t, owner: type, late_types: late_types, path: path + ["possible_types"])
206
+ end
207
+ end
208
+ if type.kind.interface?
209
+ type.orphan_types.each do |t|
210
+ add_type(t, owner: type, late_types: late_types, path: path + ["orphan_types"])
211
+ end
212
+ end
213
+ if type.kind.object?
214
+ possible_types_for_this_name = @possible_types[type.graphql_name] ||= []
215
+ possible_types_for_this_name << type
216
+ end
217
+
218
+ if type.kind.object? || type.kind.interface?
219
+ type.interface_type_memberships.each do |interface_type_membership|
220
+ case interface_type_membership
221
+ when Schema::TypeMembership
222
+ interface_type = interface_type_membership.abstract_type
223
+ # We can get these now; we'll have to get late-bound types later
224
+ if interface_type.is_a?(Module) && type.is_a?(Class)
225
+ implementers = @possible_types[interface_type.graphql_name] ||= []
226
+ implementers << type
227
+ end
228
+ when String, Schema::LateBoundType
229
+ interface_type = interface_type_membership
230
+ else
231
+ raise ArgumentError, "Invariant: unexpected type membership for #{type.graphql_name}: #{interface_type_membership.class} (#{interface_type_membership.inspect})"
232
+ end
233
+ add_type(interface_type, owner: type, late_types: late_types, path: path + ["implements"])
234
+ end
235
+ end
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
@@ -2,9 +2,12 @@
2
2
  module GraphQL
3
3
  class Schema
4
4
  class Argument
5
- include GraphQL::Schema::Member::CachedGraphQLDefinition
6
- include GraphQL::Schema::Member::AcceptsDefinition
7
5
  include GraphQL::Schema::Member::HasPath
6
+ include GraphQL::Schema::Member::HasAstNode
7
+ include GraphQL::Schema::Member::HasDirectives
8
+ include GraphQL::Schema::Member::HasDeprecationReason
9
+ include GraphQL::Schema::Member::HasValidators
10
+ include GraphQL::Schema::FindInheritedValue::EmptyObjects
8
11
 
9
12
  NO_DEFAULT = :__no_default__
10
13
 
@@ -32,30 +35,50 @@ module GraphQL
32
35
  # @param arg_name [Symbol]
33
36
  # @param type_expr
34
37
  # @param desc [String]
35
- # @param required [Boolean] if true, this argument is non-null; if false, this argument is nullable
38
+ # @param required [Boolean, :nullable] if true, this argument is non-null; if false, this argument is nullable. If `:nullable`, then the argument must be provided, though it may be `null`.
36
39
  # @param description [String]
37
40
  # @param default_value [Object]
38
41
  # @param as [Symbol] Override the keyword name when passed to a method
39
42
  # @param prepare [Symbol] A method to call to transform this argument's valuebefore sending it to field resolution
40
43
  # @param camelize [Boolean] if true, the name will be camelized when building the schema
41
44
  # @param from_resolver [Boolean] if true, a Resolver class defined this argument
42
- # @param method_access [Boolean] If false, don't build method access on legacy {Query::Arguments} instances.
43
- def initialize(arg_name = nil, type_expr = nil, desc = nil, required:, type: nil, name: nil, loads: nil, description: nil, ast_node: nil, default_value: NO_DEFAULT, as: nil, from_resolver: false, camelize: true, prepare: nil, method_access: true, owner:, &definition_block)
45
+ # @param directives [Hash{Class => Hash}]
46
+ # @param deprecation_reason [String]
47
+ # @param validates [Hash, nil] Options for building validators, if any should be applied
48
+ # @param replace_null_with_default [Boolean] if `true`, incoming values of `null` will be replaced with the configured `default_value`
49
+ def initialize(arg_name = nil, type_expr = nil, desc = nil, required: true, type: nil, name: nil, loads: nil, description: nil, ast_node: nil, default_value: NO_DEFAULT, as: nil, from_resolver: false, camelize: true, prepare: nil, owner:, validates: nil, directives: nil, deprecation_reason: nil, replace_null_with_default: false, &definition_block)
44
50
  arg_name ||= name
45
- name_str = camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s
46
- @name = name_str.freeze
51
+ @name = -(camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s)
47
52
  @type_expr = type_expr || type
48
53
  @description = desc || description
49
- @null = !required
54
+ @null = required != true
50
55
  @default_value = default_value
56
+ if replace_null_with_default
57
+ if !default_value?
58
+ raise ArgumentError, "`replace_null_with_default: true` requires a default value, please provide one with `default_value: ...`"
59
+ end
60
+ @replace_null_with_default = true
61
+ end
62
+
51
63
  @owner = owner
52
64
  @as = as
53
65
  @loads = loads
54
- @keyword = as || Schema::Member::BuildType.underscore(@name).to_sym
66
+ @keyword = as || (arg_name.is_a?(Symbol) ? arg_name : Schema::Member::BuildType.underscore(@name).to_sym)
55
67
  @prepare = prepare
56
68
  @ast_node = ast_node
57
69
  @from_resolver = from_resolver
58
- @method_access = method_access
70
+ self.deprecation_reason = deprecation_reason
71
+
72
+ if directives
73
+ directives.each do |dir_class, dir_options|
74
+ directive(dir_class, **dir_options)
75
+ end
76
+ end
77
+
78
+ self.validates(validates)
79
+ if required == :nullable
80
+ self.owner.validates(required: { argument: arg_name })
81
+ end
59
82
 
60
83
  if definition_block
61
84
  if definition_block.arity == 1
@@ -66,6 +89,10 @@ module GraphQL
66
89
  end
67
90
  end
68
91
 
92
+ def inspect
93
+ "#<#{self.class} #{path}: #{type.to_type_signature}#{description ? " @description=#{description.inspect}" : ""}>"
94
+ end
95
+
69
96
  # @return [Object] the value used when the client doesn't provide a value for this argument
70
97
  attr_reader :default_value
71
98
 
@@ -74,6 +101,10 @@ module GraphQL
74
101
  @default_value != NO_DEFAULT
75
102
  end
76
103
 
104
+ def replace_null_with_default?
105
+ @replace_null_with_default
106
+ end
107
+
77
108
  attr_writer :description
78
109
 
79
110
  # @return [String] Documentation for this argument
@@ -85,6 +116,20 @@ module GraphQL
85
116
  end
86
117
  end
87
118
 
119
+ # @return [String] Deprecation reason for this argument
120
+ def deprecation_reason(text = nil)
121
+ if text
122
+ self.deprecation_reason = text
123
+ else
124
+ super()
125
+ end
126
+ end
127
+
128
+ def deprecation_reason=(new_reason)
129
+ validate_deprecated_or_optional(null: @null, deprecation_reason: new_reason)
130
+ super
131
+ end
132
+
88
133
  def visible?(context)
89
134
  true
90
135
  end
@@ -93,48 +138,237 @@ module GraphQL
93
138
  true
94
139
  end
95
140
 
96
- def authorized?(obj, ctx)
141
+ def authorized?(obj, value, ctx)
142
+ authorized_as_type?(obj, value, ctx, as_type: type)
143
+ end
144
+
145
+ def authorized_as_type?(obj, value, ctx, as_type:)
146
+ if value.nil?
147
+ return true
148
+ end
149
+
150
+ if as_type.kind.non_null?
151
+ as_type = as_type.of_type
152
+ end
153
+
154
+ if as_type.kind.list?
155
+ value.each do |v|
156
+ if !authorized_as_type?(obj, v, ctx, as_type: as_type.of_type)
157
+ return false
158
+ end
159
+ end
160
+ elsif as_type.kind.input_object?
161
+ return as_type.authorized?(obj, value, ctx)
162
+ end
163
+ # None of the early-return conditions were activated,
164
+ # so this is authorized.
97
165
  true
98
166
  end
99
167
 
100
- def to_graphql
101
- argument = GraphQL::Argument.new
102
- argument.name = @name
103
- argument.type = -> { type }
104
- argument.description = @description
105
- argument.metadata[:type_class] = self
106
- argument.as = @as
107
- argument.method_access = @method_access
108
- if NO_DEFAULT != @default_value
109
- argument.default_value = @default_value
168
+ def type=(new_type)
169
+ validate_input_type(new_type)
170
+ # This isn't true for LateBoundTypes, but we can assume those will
171
+ # be updated via this codepath later in schema setup.
172
+ if new_type.respond_to?(:non_null?)
173
+ validate_deprecated_or_optional(null: !new_type.non_null?, deprecation_reason: deprecation_reason)
110
174
  end
111
- argument
175
+ @type = new_type
112
176
  end
113
177
 
114
178
  def type
115
- @type ||= Member::BuildType.parse_type(@type_expr, null: @null)
116
- rescue StandardError => err
117
- raise ArgumentError, "Couldn't build type for Argument #{@owner.name}.#{name}: #{err.class.name}: #{err.message}", err.backtrace
179
+ @type ||= begin
180
+ parsed_type = begin
181
+ Member::BuildType.parse_type(@type_expr, null: @null)
182
+ rescue StandardError => err
183
+ raise ArgumentError, "Couldn't build type for Argument #{@owner.name}.#{name}: #{err.class.name}: #{err.message}", err.backtrace
184
+ end
185
+ # Use the setter method to get validations
186
+ self.type = parsed_type
187
+ end
188
+ end
189
+
190
+ def statically_coercible?
191
+ return @statically_coercible if defined?(@statically_coercible)
192
+
193
+ @statically_coercible = !@prepare.is_a?(String) && !@prepare.is_a?(Symbol)
118
194
  end
119
195
 
120
196
  # Apply the {prepare} configuration to `value`, using methods from `obj`.
121
197
  # Used by the runtime.
122
198
  # @api private
123
- def prepare_value(obj, value)
199
+ def prepare_value(obj, value, context: nil)
124
200
  if value.is_a?(GraphQL::Schema::InputObject)
125
201
  value = value.prepare
126
202
  end
127
203
 
204
+ Schema::Validator.validate!(validators, obj, context, value)
205
+
128
206
  if @prepare.nil?
129
207
  value
130
208
  elsif @prepare.is_a?(String) || @prepare.is_a?(Symbol)
131
- obj.public_send(@prepare, value)
209
+ if obj.nil?
210
+ # The problem here is, we _used to_ prepare while building variables.
211
+ # But now we don't have the runtime object there.
212
+ #
213
+ # This will have to be called later, when the runtime object _is_ available.
214
+ value
215
+ else
216
+ obj.public_send(@prepare, value)
217
+ end
132
218
  elsif @prepare.respond_to?(:call)
133
- @prepare.call(value, obj.context)
219
+ @prepare.call(value, context || obj.context)
134
220
  else
135
221
  raise "Invalid prepare for #{@owner.name}.name: #{@prepare.inspect}"
136
222
  end
137
223
  end
224
+
225
+ # @api private
226
+ def coerce_into_values(parent_object, values, context, argument_values)
227
+ arg_name = graphql_name
228
+ arg_key = keyword
229
+ default_used = false
230
+
231
+ if values.key?(arg_name)
232
+ value = values[arg_name]
233
+ elsif values.key?(arg_key)
234
+ value = values[arg_key]
235
+ elsif default_value?
236
+ value = default_value
237
+ default_used = true
238
+ else
239
+ # no value at all
240
+ owner.validate_directive_argument(self, nil)
241
+ return
242
+ end
243
+
244
+ if value.nil? && replace_null_with_default?
245
+ value = default_value
246
+ default_used = true
247
+ end
248
+
249
+ loaded_value = nil
250
+ coerced_value = context.schema.error_handler.with_error_handling(context) do
251
+ type.coerce_input(value, context)
252
+ end
253
+
254
+ # If this isn't lazy, then the block returns eagerly and assigns the result here
255
+ # If it _is_ lazy, then we write the lazy to the hash, then update it later
256
+ argument_values[arg_key] = context.schema.after_lazy(coerced_value) do |resolved_coerced_value|
257
+ if loads && !from_resolver?
258
+ loaded_value = context.query.with_error_handling do
259
+ load_and_authorize_value(owner, coerced_value, context)
260
+ end
261
+ end
262
+
263
+ maybe_loaded_value = loaded_value || resolved_coerced_value
264
+ context.schema.after_lazy(maybe_loaded_value) do |resolved_loaded_value|
265
+ owner.validate_directive_argument(self, resolved_loaded_value)
266
+ prepared_value = context.schema.error_handler.with_error_handling(context) do
267
+ prepare_value(parent_object, resolved_loaded_value, context: context)
268
+ end
269
+
270
+ # TODO code smell to access such a deeply-nested constant in a distant module
271
+ argument_values[arg_key] = GraphQL::Execution::Interpreter::ArgumentValue.new(
272
+ value: prepared_value,
273
+ definition: self,
274
+ default_used: default_used,
275
+ )
276
+ end
277
+ end
278
+ end
279
+
280
+ def load_and_authorize_value(load_method_owner, coerced_value, context)
281
+ if coerced_value.nil?
282
+ return nil
283
+ end
284
+ arg_load_method = "load_#{keyword}"
285
+ if load_method_owner.respond_to?(arg_load_method)
286
+ custom_loaded_value = if load_method_owner.is_a?(Class)
287
+ load_method_owner.public_send(arg_load_method, coerced_value, context)
288
+ else
289
+ load_method_owner.public_send(arg_load_method, coerced_value)
290
+ end
291
+ context.schema.after_lazy(custom_loaded_value) do |custom_value|
292
+ if loads
293
+ if type.list?
294
+ loaded_values = custom_value.each_with_index.map { |custom_val, idx|
295
+ id = coerced_value[idx]
296
+ load_method_owner.authorize_application_object(self, id, context, custom_val)
297
+ }
298
+ context.schema.after_any_lazies(loaded_values, &:itself)
299
+ else
300
+ load_method_owner.authorize_application_object(self, coerced_value, context, custom_loaded_value)
301
+ end
302
+ else
303
+ custom_value
304
+ end
305
+ end
306
+ elsif loads
307
+ if type.list?
308
+ loaded_values = coerced_value.map { |val| load_method_owner.load_and_authorize_application_object(self, val, context) }
309
+ context.schema.after_any_lazies(loaded_values, &:itself)
310
+ else
311
+ load_method_owner.load_and_authorize_application_object(self, coerced_value, context)
312
+ end
313
+ else
314
+ coerced_value
315
+ end
316
+ end
317
+
318
+ # @api private
319
+ def validate_default_value
320
+ coerced_default_value = begin
321
+ # This is weird, but we should accept single-item default values for list-type arguments.
322
+ # If we used `coerce_isolated_input` below, it would do this for us, but it's not really
323
+ # the right thing here because we expect default values in application format (Ruby values)
324
+ # not GraphQL format (scalar values).
325
+ #
326
+ # But I don't think Schema::List#coerce_result should apply wrapping to single-item lists.
327
+ prepped_default_value = if default_value.nil?
328
+ nil
329
+ elsif (type.kind.list? || (type.kind.non_null? && type.of_type.list?)) && !default_value.respond_to?(:map)
330
+ [default_value]
331
+ else
332
+ default_value
333
+ end
334
+
335
+ type.coerce_isolated_result(prepped_default_value) unless prepped_default_value.nil?
336
+ rescue GraphQL::Schema::Enum::UnresolvedValueError
337
+ # It raises this, which is helpful at runtime, but not here...
338
+ default_value
339
+ end
340
+ res = type.valid_isolated_input?(coerced_default_value)
341
+ if !res
342
+ raise InvalidDefaultValueError.new(self)
343
+ end
344
+ end
345
+
346
+ class InvalidDefaultValueError < GraphQL::Error
347
+ def initialize(argument)
348
+ message = "`#{argument.path}` has an invalid default value: `#{argument.default_value.inspect}` isn't accepted by `#{argument.type.to_type_signature}`; update the default value or the argument type."
349
+ super(message)
350
+ end
351
+ end
352
+
353
+ private
354
+
355
+ def validate_input_type(input_type)
356
+ if input_type.is_a?(String) || input_type.is_a?(GraphQL::Schema::LateBoundType)
357
+ # Do nothing; assume this will be validated later
358
+ elsif input_type.kind.non_null? || input_type.kind.list?
359
+ validate_input_type(input_type.unwrap)
360
+ elsif !input_type.kind.input?
361
+ raise ArgumentError, "Invalid input type for #{path}: #{input_type.graphql_name}. Must be scalar, enum, or input object, not #{input_type.kind.name}."
362
+ else
363
+ # It's an input type, we're OK
364
+ end
365
+ end
366
+
367
+ def validate_deprecated_or_optional(null:, deprecation_reason:)
368
+ if deprecation_reason && !null
369
+ raise ArgumentError, "Required arguments cannot be deprecated: #{path}."
370
+ end
371
+ end
138
372
  end
139
373
  end
140
374
  end
@@ -13,6 +13,8 @@ module GraphQL
13
13
  def self.decode(encoded_text, nonce: false)
14
14
  # urlsafe_decode64 is for forward compatibility
15
15
  Base64Bp.urlsafe_decode64(encoded_text)
16
+ rescue ArgumentError
17
+ raise GraphQL::ExecutionError, "Invalid input: #{encoded_text.inspect}"
16
18
  end
17
19
  end
18
20
  end
@@ -20,7 +20,7 @@ module GraphQL
20
20
  def call(obj, args, ctx)
21
21
  method_name = @field_name
22
22
  if !obj.respond_to?(method_name)
23
- raise KeyError, "Can't resolve field #{method_name} on #{obj}"
23
+ raise KeyError, "Can't resolve field #{method_name} on #{obj.inspect}"
24
24
  else
25
25
  method_arity = obj.method(method_name).arity
26
26
  resolver = case method_arity
@@ -14,6 +14,12 @@ module GraphQL
14
14
  #
15
15
  # @api private
16
16
  class ResolveMap
17
+ module NullScalarCoerce
18
+ def self.call(val, _ctx)
19
+ val
20
+ end
21
+ end
22
+
17
23
  def initialize(user_resolve_hash)
18
24
  @resolve_hash = Hash.new do |h, k|
19
25
  # For each type name, provide a new hash if one wasn't given:
@@ -21,7 +27,7 @@ module GraphQL
21
27
  if k2 == "coerce_input" || k2 == "coerce_result"
22
28
  # This isn't an object field, it's a scalar coerce function.
23
29
  # Use a passthrough
24
- Builder::NullScalarCoerce
30
+ NullScalarCoerce
25
31
  else
26
32
  # For each field, provide a resolver that will
27
33
  # make runtime checks & replace itself
@@ -39,8 +45,10 @@ module GraphQL
39
45
  @resolve_hash[type_name_s][field_name.to_s] = resolve_fn
40
46
  end
41
47
  when Proc
42
- # for example, __resolve_type
48
+ # for example, "resolve_type"
43
49
  @resolve_hash[type_name_s] = fields
50
+ else
51
+ raise ArgumentError, "Unexpected resolve hash value for #{type_name.inspect}: #{fields.inspect} (#{fields.class})"
44
52
  end
45
53
  end
46
54
 
@@ -53,16 +61,16 @@ module GraphQL
53
61
  end
54
62
 
55
63
  def call(type, field, obj, args, ctx)
56
- resolver = @resolve_hash[type.name][field.name]
64
+ resolver = @resolve_hash[type.graphql_name][field.graphql_name]
57
65
  resolver.call(obj, args, ctx)
58
66
  end
59
67
 
60
68
  def coerce_input(type, value, ctx)
61
- @resolve_hash[type.name]["coerce_input"].call(value, ctx)
69
+ @resolve_hash[type.graphql_name]["coerce_input"].call(value, ctx)
62
70
  end
63
71
 
64
72
  def coerce_result(type, value, ctx)
65
- @resolve_hash[type.name]["coerce_result"].call(value, ctx)
73
+ @resolve_hash[type.graphql_name]["coerce_result"].call(value, ctx)
66
74
  end
67
75
  end
68
76
  end