graphql 1.9.18 → 1.13.24

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.
Files changed (353) 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/analyze_query.rb +7 -0
  49. data/lib/graphql/analysis/ast/field_usage.rb +29 -2
  50. data/lib/graphql/analysis/ast/query_complexity.rb +174 -67
  51. data/lib/graphql/analysis/ast/visitor.rb +16 -7
  52. data/lib/graphql/analysis/ast.rb +21 -11
  53. data/lib/graphql/argument.rb +8 -36
  54. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  55. data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
  56. data/lib/graphql/backtrace/table.rb +44 -5
  57. data/lib/graphql/backtrace/traced_error.rb +0 -1
  58. data/lib/graphql/backtrace/tracer.rb +40 -9
  59. data/lib/graphql/backtrace.rb +28 -19
  60. data/lib/graphql/backwards_compatibility.rb +2 -1
  61. data/lib/graphql/base_type.rb +10 -4
  62. data/lib/graphql/boolean_type.rb +1 -1
  63. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +2 -2
  64. data/lib/graphql/compatibility/execution_specification.rb +1 -0
  65. data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
  66. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +5 -9
  67. data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
  68. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
  69. data/lib/graphql/dataloader/null_dataloader.rb +22 -0
  70. data/lib/graphql/dataloader/request.rb +19 -0
  71. data/lib/graphql/dataloader/request_all.rb +19 -0
  72. data/lib/graphql/dataloader/source.rb +155 -0
  73. data/lib/graphql/dataloader.rb +308 -0
  74. data/lib/graphql/date_encoding_error.rb +16 -0
  75. data/lib/graphql/define/assign_enum_value.rb +1 -1
  76. data/lib/graphql/define/assign_global_id_field.rb +2 -2
  77. data/lib/graphql/define/assign_object_field.rb +1 -1
  78. data/lib/graphql/define/defined_object_proxy.rb +5 -8
  79. data/lib/graphql/define/instance_definable.rb +60 -110
  80. data/lib/graphql/define/type_definer.rb +5 -5
  81. data/lib/graphql/deprecated_dsl.rb +18 -5
  82. data/lib/graphql/deprecation.rb +9 -0
  83. data/lib/graphql/directive/deprecated_directive.rb +1 -12
  84. data/lib/graphql/directive/include_directive.rb +1 -1
  85. data/lib/graphql/directive/skip_directive.rb +1 -1
  86. data/lib/graphql/directive.rb +9 -6
  87. data/lib/graphql/enum_type.rb +14 -74
  88. data/lib/graphql/execution/directive_checks.rb +2 -2
  89. data/lib/graphql/execution/errors.rb +110 -8
  90. data/lib/graphql/execution/execute.rb +8 -1
  91. data/lib/graphql/execution/instrumentation.rb +1 -1
  92. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  93. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  94. data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
  95. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  96. data/lib/graphql/execution/interpreter/resolve.rb +37 -25
  97. data/lib/graphql/execution/interpreter/runtime.rb +721 -386
  98. data/lib/graphql/execution/interpreter.rb +42 -19
  99. data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
  100. data/lib/graphql/execution/lazy.rb +5 -1
  101. data/lib/graphql/execution/lookahead.rb +39 -114
  102. data/lib/graphql/execution/multiplex.rb +50 -25
  103. data/lib/graphql/field.rb +15 -119
  104. data/lib/graphql/filter.rb +1 -1
  105. data/lib/graphql/float_type.rb +1 -1
  106. data/lib/graphql/function.rb +5 -30
  107. data/lib/graphql/id_type.rb +1 -1
  108. data/lib/graphql/input_object_type.rb +9 -25
  109. data/lib/graphql/int_type.rb +1 -1
  110. data/lib/graphql/integer_decoding_error.rb +17 -0
  111. data/lib/graphql/integer_encoding_error.rb +18 -2
  112. data/lib/graphql/interface_type.rb +10 -24
  113. data/lib/graphql/internal_representation/document.rb +2 -2
  114. data/lib/graphql/internal_representation/rewrite.rb +1 -1
  115. data/lib/graphql/internal_representation/scope.rb +2 -2
  116. data/lib/graphql/internal_representation/visit.rb +2 -2
  117. data/lib/graphql/introspection/base_object.rb +2 -5
  118. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  119. data/lib/graphql/introspection/directive_type.rb +12 -6
  120. data/lib/graphql/introspection/entry_points.rb +9 -9
  121. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  122. data/lib/graphql/introspection/field_type.rb +9 -5
  123. data/lib/graphql/introspection/input_value_type.rb +41 -11
  124. data/lib/graphql/introspection/introspection_query.rb +6 -92
  125. data/lib/graphql/introspection/schema_type.rb +12 -12
  126. data/lib/graphql/introspection/type_type.rb +27 -17
  127. data/lib/graphql/introspection.rb +99 -0
  128. data/lib/graphql/invalid_null_error.rb +18 -0
  129. data/lib/graphql/language/block_string.rb +20 -5
  130. data/lib/graphql/language/cache.rb +37 -0
  131. data/lib/graphql/language/definition_slice.rb +21 -10
  132. data/lib/graphql/language/document_from_schema_definition.rb +116 -63
  133. data/lib/graphql/language/lexer.rb +53 -27
  134. data/lib/graphql/language/lexer.rl +5 -3
  135. data/lib/graphql/language/nodes.rb +67 -93
  136. data/lib/graphql/language/parser.rb +929 -896
  137. data/lib/graphql/language/parser.y +125 -102
  138. data/lib/graphql/language/printer.rb +11 -2
  139. data/lib/graphql/language/sanitized_printer.rb +222 -0
  140. data/lib/graphql/language/token.rb +0 -4
  141. data/lib/graphql/language/visitor.rb +2 -2
  142. data/lib/graphql/language.rb +3 -1
  143. data/lib/graphql/name_validator.rb +2 -7
  144. data/lib/graphql/non_null_type.rb +0 -10
  145. data/lib/graphql/object_type.rb +47 -58
  146. data/lib/graphql/pagination/active_record_relation_connection.rb +85 -0
  147. data/lib/graphql/pagination/array_connection.rb +77 -0
  148. data/lib/graphql/pagination/connection.rb +226 -0
  149. data/lib/graphql/pagination/connections.rb +160 -0
  150. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  151. data/lib/graphql/pagination/relation_connection.rb +226 -0
  152. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  153. data/lib/graphql/pagination.rb +6 -0
  154. data/lib/graphql/parse_error.rb +0 -1
  155. data/lib/graphql/query/arguments.rb +6 -4
  156. data/lib/graphql/query/arguments_cache.rb +1 -2
  157. data/lib/graphql/query/context.rb +52 -7
  158. data/lib/graphql/query/executor.rb +0 -1
  159. data/lib/graphql/query/fingerprint.rb +26 -0
  160. data/lib/graphql/query/input_validation_result.rb +32 -6
  161. data/lib/graphql/query/literal_input.rb +31 -11
  162. data/lib/graphql/query/null_context.rb +24 -8
  163. data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
  164. data/lib/graphql/query/serial_execution.rb +1 -0
  165. data/lib/graphql/query/validation_pipeline.rb +6 -4
  166. data/lib/graphql/query/variable_validation_error.rb +3 -3
  167. data/lib/graphql/query/variables.rb +50 -10
  168. data/lib/graphql/query.rb +77 -18
  169. data/lib/graphql/railtie.rb +9 -1
  170. data/lib/graphql/rake_task/validate.rb +3 -0
  171. data/lib/graphql/rake_task.rb +12 -9
  172. data/lib/graphql/relay/array_connection.rb +10 -12
  173. data/lib/graphql/relay/base_connection.rb +30 -13
  174. data/lib/graphql/relay/connection_instrumentation.rb +4 -4
  175. data/lib/graphql/relay/connection_type.rb +18 -4
  176. data/lib/graphql/relay/edge_type.rb +1 -0
  177. data/lib/graphql/relay/edges_instrumentation.rb +1 -2
  178. data/lib/graphql/relay/global_id_resolve.rb +1 -2
  179. data/lib/graphql/relay/mutation.rb +3 -87
  180. data/lib/graphql/relay/node.rb +3 -0
  181. data/lib/graphql/relay/page_info.rb +1 -1
  182. data/lib/graphql/relay/range_add.rb +27 -9
  183. data/lib/graphql/relay/relation_connection.rb +8 -10
  184. data/lib/graphql/relay/type_extensions.rb +2 -0
  185. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  186. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  187. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  188. data/lib/graphql/rubocop.rb +4 -0
  189. data/lib/graphql/scalar_type.rb +18 -60
  190. data/lib/graphql/schema/addition.rb +247 -0
  191. data/lib/graphql/schema/argument.rb +274 -18
  192. data/lib/graphql/schema/base_64_encoder.rb +2 -0
  193. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
  194. data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
  195. data/lib/graphql/schema/build_from_definition.rb +320 -219
  196. data/lib/graphql/schema/built_in_types.rb +5 -5
  197. data/lib/graphql/schema/default_type_error.rb +2 -0
  198. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  199. data/lib/graphql/schema/directive/feature.rb +1 -1
  200. data/lib/graphql/schema/directive/flagged.rb +57 -0
  201. data/lib/graphql/schema/directive/include.rb +2 -2
  202. data/lib/graphql/schema/directive/skip.rb +2 -2
  203. data/lib/graphql/schema/directive/transform.rb +14 -2
  204. data/lib/graphql/schema/directive.rb +130 -6
  205. data/lib/graphql/schema/enum.rb +121 -12
  206. data/lib/graphql/schema/enum_value.rb +24 -7
  207. data/lib/graphql/schema/field/connection_extension.rb +46 -20
  208. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  209. data/lib/graphql/schema/field.rb +465 -181
  210. data/lib/graphql/schema/field_extension.rb +89 -2
  211. data/lib/graphql/schema/find_inherited_value.rb +17 -1
  212. data/lib/graphql/schema/finder.rb +16 -14
  213. data/lib/graphql/schema/input_object.rb +172 -37
  214. data/lib/graphql/schema/interface.rb +39 -25
  215. data/lib/graphql/schema/introspection_system.rb +106 -38
  216. data/lib/graphql/schema/late_bound_type.rb +3 -2
  217. data/lib/graphql/schema/list.rb +65 -1
  218. data/lib/graphql/schema/loader.rb +145 -102
  219. data/lib/graphql/schema/member/accepts_definition.rb +15 -3
  220. data/lib/graphql/schema/member/base_dsl_methods.rb +34 -28
  221. data/lib/graphql/schema/member/build_type.rb +19 -8
  222. data/lib/graphql/schema/member/cached_graphql_definition.rb +34 -2
  223. data/lib/graphql/schema/member/has_arguments.rb +206 -13
  224. data/lib/graphql/schema/member/has_ast_node.rb +20 -0
  225. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  226. data/lib/graphql/schema/member/has_directives.rb +98 -0
  227. data/lib/graphql/schema/member/has_fields.rb +97 -32
  228. data/lib/graphql/schema/member/has_interfaces.rb +100 -0
  229. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  230. data/lib/graphql/schema/member/has_validators.rb +31 -0
  231. data/lib/graphql/schema/member/instrumentation.rb +0 -1
  232. data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
  233. data/lib/graphql/schema/member/validates_input.rb +33 -0
  234. data/lib/graphql/schema/member.rb +11 -0
  235. data/lib/graphql/schema/middleware_chain.rb +1 -1
  236. data/lib/graphql/schema/mutation.rb +4 -0
  237. data/lib/graphql/schema/non_null.rb +37 -1
  238. data/lib/graphql/schema/object.rb +51 -38
  239. data/lib/graphql/schema/possible_types.rb +9 -4
  240. data/lib/graphql/schema/printer.rb +16 -35
  241. data/lib/graphql/schema/relay_classic_mutation.rb +40 -4
  242. data/lib/graphql/schema/resolver/has_payload_type.rb +34 -4
  243. data/lib/graphql/schema/resolver.rb +133 -79
  244. data/lib/graphql/schema/scalar.rb +43 -3
  245. data/lib/graphql/schema/subscription.rb +57 -21
  246. data/lib/graphql/schema/timeout.rb +29 -15
  247. data/lib/graphql/schema/timeout_middleware.rb +3 -1
  248. data/lib/graphql/schema/traversal.rb +2 -2
  249. data/lib/graphql/schema/type_expression.rb +21 -13
  250. data/lib/graphql/schema/type_membership.rb +19 -5
  251. data/lib/graphql/schema/union.rb +44 -3
  252. data/lib/graphql/schema/unique_within_type.rb +1 -2
  253. data/lib/graphql/schema/validation.rb +14 -4
  254. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  255. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  256. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  257. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  258. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  259. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  260. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  261. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  262. data/lib/graphql/schema/validator.rb +171 -0
  263. data/lib/graphql/schema/warden.rb +193 -34
  264. data/lib/graphql/schema.rb +882 -247
  265. data/lib/graphql/static_validation/all_rules.rb +2 -0
  266. data/lib/graphql/static_validation/base_visitor.rb +17 -10
  267. data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
  268. data/lib/graphql/static_validation/error.rb +3 -1
  269. data/lib/graphql/static_validation/literal_validator.rb +51 -26
  270. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +45 -83
  271. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +22 -6
  272. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +35 -26
  273. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  274. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
  275. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -2
  276. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
  277. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
  278. data/lib/graphql/static_validation/rules/fields_will_merge.rb +94 -51
  279. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  280. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  281. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  282. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  283. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  284. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  285. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  286. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -2
  287. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +9 -10
  288. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
  289. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
  290. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -14
  291. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  292. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
  293. data/lib/graphql/static_validation/type_stack.rb +2 -2
  294. data/lib/graphql/static_validation/validation_context.rb +13 -3
  295. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  296. data/lib/graphql/static_validation/validator.rb +43 -9
  297. data/lib/graphql/static_validation.rb +1 -0
  298. data/lib/graphql/string_encoding_error.rb +13 -3
  299. data/lib/graphql/string_type.rb +1 -1
  300. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +123 -22
  301. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  302. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
  303. data/lib/graphql/subscriptions/event.rb +84 -30
  304. data/lib/graphql/subscriptions/instrumentation.rb +10 -6
  305. data/lib/graphql/subscriptions/serialize.rb +53 -6
  306. data/lib/graphql/subscriptions/subscription_root.rb +15 -5
  307. data/lib/graphql/subscriptions.rb +117 -49
  308. data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
  309. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  310. data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
  311. data/lib/graphql/tracing/data_dog_tracing.rb +32 -15
  312. data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
  313. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  314. data/lib/graphql/tracing/platform_tracing.rb +66 -10
  315. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  316. data/lib/graphql/tracing/prometheus_tracing.rb +8 -0
  317. data/lib/graphql/tracing/scout_tracing.rb +19 -0
  318. data/lib/graphql/tracing/skylight_tracing.rb +9 -1
  319. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  320. data/lib/graphql/tracing.rb +15 -35
  321. data/lib/graphql/types/big_int.rb +5 -1
  322. data/lib/graphql/types/int.rb +10 -3
  323. data/lib/graphql/types/iso_8601_date.rb +16 -8
  324. data/lib/graphql/types/iso_8601_date_time.rb +32 -10
  325. data/lib/graphql/types/relay/base_connection.rb +6 -88
  326. data/lib/graphql/types/relay/base_edge.rb +2 -34
  327. data/lib/graphql/types/relay/connection_behaviors.rb +174 -0
  328. data/lib/graphql/types/relay/default_relay.rb +31 -0
  329. data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
  330. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  331. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  332. data/lib/graphql/types/relay/node.rb +2 -4
  333. data/lib/graphql/types/relay/node_behaviors.rb +15 -0
  334. data/lib/graphql/types/relay/node_field.rb +3 -22
  335. data/lib/graphql/types/relay/nodes_field.rb +16 -18
  336. data/lib/graphql/types/relay/page_info.rb +2 -14
  337. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  338. data/lib/graphql/types/relay.rb +11 -3
  339. data/lib/graphql/types/string.rb +8 -2
  340. data/lib/graphql/unauthorized_error.rb +2 -2
  341. data/lib/graphql/union_type.rb +5 -25
  342. data/lib/graphql/unresolved_type_error.rb +2 -2
  343. data/lib/graphql/upgrader/member.rb +1 -0
  344. data/lib/graphql/upgrader/schema.rb +1 -0
  345. data/lib/graphql/version.rb +1 -1
  346. data/lib/graphql.rb +87 -31
  347. data/readme.md +3 -6
  348. metadata +126 -124
  349. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  350. data/lib/graphql/literal_validation_error.rb +0 -6
  351. data/lib/graphql/types/relay/base_field.rb +0 -22
  352. data/lib/graphql/types/relay/base_interface.rb +0 -29
  353. data/lib/graphql/types/relay/base_object.rb +0 -26
@@ -5,6 +5,11 @@ module GraphQL
5
5
  include GraphQL::Schema::Member::CachedGraphQLDefinition
6
6
  include GraphQL::Schema::Member::AcceptsDefinition
7
7
  include GraphQL::Schema::Member::HasPath
8
+ include GraphQL::Schema::Member::HasAstNode
9
+ include GraphQL::Schema::Member::HasDirectives
10
+ include GraphQL::Schema::Member::HasDeprecationReason
11
+ include GraphQL::Schema::Member::HasValidators
12
+ include GraphQL::Schema::FindInheritedValue::EmptyObjects
8
13
 
9
14
  NO_DEFAULT = :__no_default__
10
15
 
@@ -32,7 +37,7 @@ module GraphQL
32
37
  # @param arg_name [Symbol]
33
38
  # @param type_expr
34
39
  # @param desc [String]
35
- # @param required [Boolean] if true, this argument is non-null; if false, this argument is nullable
40
+ # @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
41
  # @param description [String]
37
42
  # @param default_value [Object]
38
43
  # @param as [Symbol] Override the keyword name when passed to a method
@@ -40,30 +45,54 @@ module GraphQL
40
45
  # @param camelize [Boolean] if true, the name will be camelized when building the schema
41
46
  # @param from_resolver [Boolean] if true, a Resolver class defined this argument
42
47
  # @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)
48
+ # @param directives [Hash{Class => Hash}]
49
+ # @param deprecation_reason [String]
50
+ # @param validates [Hash, nil] Options for building validators, if any should be applied
51
+ # @param replace_null_with_default [Boolean] if `true`, incoming values of `null` will be replaced with the configured `default_value`
52
+ 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, method_access: true, owner:, validates: nil, directives: nil, deprecation_reason: nil, replace_null_with_default: false, &definition_block)
44
53
  arg_name ||= name
45
- name_str = camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s
46
- @name = name_str.freeze
54
+ @name = -(camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s)
55
+ NameValidator.validate!(@name)
47
56
  @type_expr = type_expr || type
48
57
  @description = desc || description
49
- @null = !required
58
+ @null = required != true
50
59
  @default_value = default_value
60
+ if replace_null_with_default
61
+ if !default_value?
62
+ raise ArgumentError, "`replace_null_with_default: true` requires a default value, please provide one with `default_value: ...`"
63
+ end
64
+ @replace_null_with_default = true
65
+ end
66
+
51
67
  @owner = owner
52
68
  @as = as
53
69
  @loads = loads
54
- @keyword = as || Schema::Member::BuildType.underscore(@name).to_sym
70
+ @keyword = as || (arg_name.is_a?(Symbol) ? arg_name : Schema::Member::BuildType.underscore(@name).to_sym)
55
71
  @prepare = prepare
56
72
  @ast_node = ast_node
57
73
  @from_resolver = from_resolver
58
74
  @method_access = method_access
75
+ self.deprecation_reason = deprecation_reason
59
76
 
60
- if definition_block
61
- if definition_block.arity == 1
62
- instance_exec(self, &definition_block)
63
- else
64
- instance_eval(&definition_block)
77
+ if directives
78
+ directives.each do |dir_class, dir_options|
79
+ directive(dir_class, **dir_options)
65
80
  end
66
81
  end
82
+
83
+ self.validates(validates)
84
+ if required == :nullable
85
+ self.owner.validates(required: { argument: arg_name })
86
+ end
87
+
88
+ if definition_block
89
+ # `self` will still be self, it will also be the first argument to the block:
90
+ instance_exec(self, &definition_block)
91
+ end
92
+ end
93
+
94
+ def inspect
95
+ "#<#{self.class} #{path}: #{type.to_type_signature}#{description ? " @description=#{description.inspect}" : ""}>"
67
96
  end
68
97
 
69
98
  # @return [Object] the value used when the client doesn't provide a value for this argument
@@ -74,6 +103,10 @@ module GraphQL
74
103
  @default_value != NO_DEFAULT
75
104
  end
76
105
 
106
+ def replace_null_with_default?
107
+ @replace_null_with_default
108
+ end
109
+
77
110
  attr_writer :description
78
111
 
79
112
  # @return [String] Documentation for this argument
@@ -85,6 +118,20 @@ module GraphQL
85
118
  end
86
119
  end
87
120
 
121
+ # @return [String] Deprecation reason for this argument
122
+ def deprecation_reason(text = nil)
123
+ if text
124
+ self.deprecation_reason = text
125
+ else
126
+ super()
127
+ end
128
+ end
129
+
130
+ def deprecation_reason=(new_reason)
131
+ validate_deprecated_or_optional(null: @null, deprecation_reason: new_reason)
132
+ super
133
+ end
134
+
88
135
  def visible?(context)
89
136
  true
90
137
  end
@@ -93,10 +140,35 @@ module GraphQL
93
140
  true
94
141
  end
95
142
 
96
- def authorized?(obj, ctx)
143
+ def authorized?(obj, value, ctx)
144
+ authorized_as_type?(obj, value, ctx, as_type: type)
145
+ end
146
+
147
+ def authorized_as_type?(obj, value, ctx, as_type:)
148
+ if value.nil?
149
+ return true
150
+ end
151
+
152
+ if as_type.kind.non_null?
153
+ as_type = as_type.of_type
154
+ end
155
+
156
+ if as_type.kind.list?
157
+ value.each do |v|
158
+ if !authorized_as_type?(obj, v, ctx, as_type: as_type.of_type)
159
+ return false
160
+ end
161
+ end
162
+ elsif as_type.kind.input_object?
163
+ return as_type.authorized?(obj, value, ctx)
164
+ end
165
+ # None of the early-return conditions were activated,
166
+ # so this is authorized.
97
167
  true
98
168
  end
99
169
 
170
+ prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
171
+
100
172
  def to_graphql
101
173
  argument = GraphQL::Argument.new
102
174
  argument.name = @name
@@ -104,37 +176,221 @@ module GraphQL
104
176
  argument.description = @description
105
177
  argument.metadata[:type_class] = self
106
178
  argument.as = @as
179
+ argument.ast_node = ast_node
107
180
  argument.method_access = @method_access
108
181
  if NO_DEFAULT != @default_value
109
182
  argument.default_value = @default_value
110
183
  end
184
+ if self.deprecation_reason
185
+ argument.deprecation_reason = self.deprecation_reason
186
+ end
111
187
  argument
112
188
  end
113
189
 
190
+ def type=(new_type)
191
+ validate_input_type(new_type)
192
+ # This isn't true for LateBoundTypes, but we can assume those will
193
+ # be updated via this codepath later in schema setup.
194
+ if new_type.respond_to?(:non_null?)
195
+ validate_deprecated_or_optional(null: !new_type.non_null?, deprecation_reason: deprecation_reason)
196
+ end
197
+ @type = new_type
198
+ end
199
+
114
200
  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
201
+ @type ||= begin
202
+ parsed_type = begin
203
+ Member::BuildType.parse_type(@type_expr, null: @null)
204
+ rescue StandardError => err
205
+ raise ArgumentError, "Couldn't build type for Argument #{@owner.name}.#{name}: #{err.class.name}: #{err.message}", err.backtrace
206
+ end
207
+ # Use the setter method to get validations
208
+ self.type = parsed_type
209
+ end
210
+ end
211
+
212
+ def statically_coercible?
213
+ return @statically_coercible if defined?(@statically_coercible)
214
+
215
+ @statically_coercible = !@prepare.is_a?(String) && !@prepare.is_a?(Symbol)
118
216
  end
119
217
 
120
218
  # Apply the {prepare} configuration to `value`, using methods from `obj`.
121
219
  # Used by the runtime.
122
220
  # @api private
123
- def prepare_value(obj, value)
221
+ def prepare_value(obj, value, context: nil)
124
222
  if value.is_a?(GraphQL::Schema::InputObject)
125
223
  value = value.prepare
126
224
  end
127
225
 
226
+ Schema::Validator.validate!(validators, obj, context, value)
227
+
128
228
  if @prepare.nil?
129
229
  value
130
230
  elsif @prepare.is_a?(String) || @prepare.is_a?(Symbol)
131
- obj.public_send(@prepare, value)
231
+ if obj.nil?
232
+ # The problem here is, we _used to_ prepare while building variables.
233
+ # But now we don't have the runtime object there.
234
+ #
235
+ # This will have to be called later, when the runtime object _is_ available.
236
+ value
237
+ else
238
+ obj.public_send(@prepare, value)
239
+ end
132
240
  elsif @prepare.respond_to?(:call)
133
- @prepare.call(value, obj.context)
241
+ @prepare.call(value, context || obj.context)
134
242
  else
135
243
  raise "Invalid prepare for #{@owner.name}.name: #{@prepare.inspect}"
136
244
  end
137
245
  end
246
+
247
+ # @api private
248
+ def coerce_into_values(parent_object, values, context, argument_values)
249
+ arg_name = graphql_name
250
+ arg_key = keyword
251
+ default_used = false
252
+
253
+ if values.key?(arg_name)
254
+ value = values[arg_name]
255
+ elsif values.key?(arg_key)
256
+ value = values[arg_key]
257
+ elsif default_value?
258
+ value = default_value
259
+ default_used = true
260
+ else
261
+ # no value at all
262
+ owner.validate_directive_argument(self, nil)
263
+ return
264
+ end
265
+
266
+ if value.nil? && replace_null_with_default?
267
+ value = default_value
268
+ default_used = true
269
+ end
270
+
271
+ loaded_value = nil
272
+ coerced_value = context.schema.error_handler.with_error_handling(context) do
273
+ type.coerce_input(value, context)
274
+ end
275
+
276
+ # If this isn't lazy, then the block returns eagerly and assigns the result here
277
+ # If it _is_ lazy, then we write the lazy to the hash, then update it later
278
+ argument_values[arg_key] = context.schema.after_lazy(coerced_value) do |resolved_coerced_value|
279
+ if loads && !from_resolver?
280
+ loaded_value = context.query.with_error_handling do
281
+ load_and_authorize_value(owner, coerced_value, context)
282
+ end
283
+ end
284
+
285
+ maybe_loaded_value = loaded_value || resolved_coerced_value
286
+ context.schema.after_lazy(maybe_loaded_value) do |resolved_loaded_value|
287
+ owner.validate_directive_argument(self, resolved_loaded_value)
288
+ prepared_value = context.schema.error_handler.with_error_handling(context) do
289
+ prepare_value(parent_object, resolved_loaded_value, context: context)
290
+ end
291
+
292
+ # TODO code smell to access such a deeply-nested constant in a distant module
293
+ argument_values[arg_key] = GraphQL::Execution::Interpreter::ArgumentValue.new(
294
+ value: prepared_value,
295
+ definition: self,
296
+ default_used: default_used,
297
+ )
298
+ end
299
+ end
300
+ end
301
+
302
+ def load_and_authorize_value(load_method_owner, coerced_value, context)
303
+ if coerced_value.nil?
304
+ return nil
305
+ end
306
+ arg_load_method = "load_#{keyword}"
307
+ if load_method_owner.respond_to?(arg_load_method)
308
+ custom_loaded_value = if load_method_owner.is_a?(Class)
309
+ load_method_owner.public_send(arg_load_method, coerced_value, context)
310
+ else
311
+ load_method_owner.public_send(arg_load_method, coerced_value)
312
+ end
313
+ context.schema.after_lazy(custom_loaded_value) do |custom_value|
314
+ if loads
315
+ if type.list?
316
+ loaded_values = custom_value.each_with_index.map { |custom_val, idx|
317
+ id = coerced_value[idx]
318
+ load_method_owner.authorize_application_object(self, id, context, custom_val)
319
+ }
320
+ context.schema.after_any_lazies(loaded_values, &:itself)
321
+ else
322
+ load_method_owner.authorize_application_object(self, coerced_value, context, custom_loaded_value)
323
+ end
324
+ else
325
+ custom_value
326
+ end
327
+ end
328
+ elsif loads
329
+ if type.list?
330
+ loaded_values = coerced_value.map { |val| load_method_owner.load_and_authorize_application_object(self, val, context) }
331
+ context.schema.after_any_lazies(loaded_values, &:itself)
332
+ else
333
+ load_method_owner.load_and_authorize_application_object(self, coerced_value, context)
334
+ end
335
+ else
336
+ coerced_value
337
+ end
338
+ end
339
+
340
+ # @api private
341
+ def validate_default_value
342
+ coerced_default_value = begin
343
+ # This is weird, but we should accept single-item default values for list-type arguments.
344
+ # If we used `coerce_isolated_input` below, it would do this for us, but it's not really
345
+ # the right thing here because we expect default values in application format (Ruby values)
346
+ # not GraphQL format (scalar values).
347
+ #
348
+ # But I don't think Schema::List#coerce_result should apply wrapping to single-item lists.
349
+ prepped_default_value = if default_value.nil?
350
+ nil
351
+ elsif (type.kind.list? || (type.kind.non_null? && type.of_type.list?)) && !default_value.respond_to?(:map)
352
+ [default_value]
353
+ else
354
+ default_value
355
+ end
356
+
357
+ type.coerce_isolated_result(prepped_default_value) unless prepped_default_value.nil?
358
+ rescue GraphQL::Schema::Enum::UnresolvedValueError
359
+ # It raises this, which is helpful at runtime, but not here...
360
+ default_value
361
+ end
362
+ res = type.valid_isolated_input?(coerced_default_value)
363
+ if !res
364
+ raise InvalidDefaultValueError.new(self)
365
+ end
366
+ end
367
+
368
+ class InvalidDefaultValueError < GraphQL::Error
369
+ def initialize(argument)
370
+ 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."
371
+ super(message)
372
+ end
373
+ end
374
+
375
+ private
376
+
377
+ def validate_input_type(input_type)
378
+ if input_type.is_a?(String) || input_type.is_a?(GraphQL::Schema::LateBoundType)
379
+ # Do nothing; assume this will be validated later
380
+ elsif input_type.kind.non_null? || input_type.kind.list?
381
+ validate_input_type(input_type.unwrap)
382
+ elsif !input_type.kind.input?
383
+ raise ArgumentError, "Invalid input type for #{path}: #{input_type.graphql_name}. Must be scalar, enum, or input object, not #{input_type.kind.name}."
384
+ else
385
+ # It's an input type, we're OK
386
+ end
387
+ end
388
+
389
+ def validate_deprecated_or_optional(null:, deprecation_reason:)
390
+ if deprecation_reason && !null
391
+ raise ArgumentError, "Required arguments cannot be deprecated: #{path}."
392
+ end
393
+ end
138
394
  end
139
395
  end
140
396
  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