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
@@ -1,8 +1,12 @@
1
1
  # frozen_string_literal: true
2
+ require "fiber"
3
+ require "graphql/execution/interpreter/argument_value"
4
+ require "graphql/execution/interpreter/arguments"
5
+ require "graphql/execution/interpreter/arguments_cache"
2
6
  require "graphql/execution/interpreter/execution_errors"
3
- require "graphql/execution/interpreter/hash_response"
4
7
  require "graphql/execution/interpreter/runtime"
5
8
  require "graphql/execution/interpreter/resolve"
9
+ require "graphql/execution/interpreter/handles_raw_value"
6
10
 
7
11
  module GraphQL
8
12
  module Execution
@@ -14,19 +18,18 @@ module GraphQL
14
18
  def execute(_operation, _root_type, query)
15
19
  runtime = evaluate(query)
16
20
  sync_lazies(query: query)
17
- runtime.final_value
21
+ runtime.final_result
18
22
  end
19
23
 
20
- def self.use(schema_defn)
21
- schema_defn.target.interpreter = true
22
- # Reach through the legacy objects for the actual class defn
23
- schema_class = schema_defn.target.class
24
- # This is not good, since both of these are holding state now,
25
- # we have to update both :(
26
- [schema_class, schema_defn].each do |schema_config|
27
- schema_config.query_execution_strategy(GraphQL::Execution::Interpreter)
28
- schema_config.mutation_execution_strategy(GraphQL::Execution::Interpreter)
29
- schema_config.subscription_execution_strategy(GraphQL::Execution::Interpreter)
24
+ def self.use(schema_class)
25
+ if schema_class.interpreter?
26
+ definition_line = caller(2, 1).first
27
+ GraphQL::Deprecation.warn("GraphQL::Execution::Interpreter is now the default; remove `use GraphQL::Execution::Interpreter` from the schema definition (#{definition_line})")
28
+ else
29
+ schema_class.query_execution_strategy(self)
30
+ schema_class.mutation_execution_strategy(self)
31
+ schema_class.subscription_execution_strategy(self)
32
+ schema_class.add_subscription_extension_if_necessary
30
33
  end
31
34
  end
32
35
 
@@ -53,7 +56,7 @@ module GraphQL
53
56
 
54
57
  def self.finish_query(query, _multiplex)
55
58
  {
56
- "data" => query.context.namespace(:interpreter)[:runtime].final_value
59
+ "data" => query.context.namespace(:interpreter)[:runtime].final_result
57
60
  }
58
61
  end
59
62
 
@@ -63,10 +66,7 @@ module GraphQL
63
66
  # Although queries in a multiplex _share_ an Interpreter instance,
64
67
  # they also have another item of state, which is private to that query
65
68
  # in particular, assign it here:
66
- runtime = Runtime.new(
67
- query: query,
68
- response: HashResponse.new,
69
- )
69
+ runtime = Runtime.new(query: query)
70
70
  query.context.namespace(:interpreter)[:runtime] = runtime
71
71
 
72
72
  query.trace("execute_query", {query: query}) do
@@ -87,11 +87,34 @@ module GraphQL
87
87
  final_values = queries.map do |query|
88
88
  runtime = query.context.namespace(:interpreter)[:runtime]
89
89
  # it might not be present if the query has an error
90
- runtime ? runtime.final_value : nil
90
+ runtime ? runtime.final_result : nil
91
91
  end
92
92
  final_values.compact!
93
93
  tracer.trace("execute_query_lazy", {multiplex: multiplex, query: query}) do
94
- Interpreter::Resolve.resolve_all(final_values)
94
+ Interpreter::Resolve.resolve_all(final_values, multiplex.dataloader)
95
+ end
96
+ queries.each do |query|
97
+ runtime = query.context.namespace(:interpreter)[:runtime]
98
+ if runtime
99
+ runtime.delete_interpreter_context(:current_path)
100
+ runtime.delete_interpreter_context(:current_field)
101
+ runtime.delete_interpreter_context(:current_object)
102
+ runtime.delete_interpreter_context(:current_arguments)
103
+ end
104
+ end
105
+ nil
106
+ end
107
+
108
+ class ListResultFailedError < GraphQL::Error
109
+ def initialize(value:, path:, field:)
110
+ message = "Failed to build a GraphQL list result for field `#{field.path}` at path `#{path.join(".")}`.\n".dup
111
+
112
+ message << "Expected `#{value.inspect}` (#{value.class}) to implement `.each` to satisfy the GraphQL return type `#{field.type.to_type_signature}`.\n"
113
+
114
+ if field.connection?
115
+ message << "\nThis field was treated as a Relay-style connection; add `connection: false` to the `field(...)` to disable this behavior."
116
+ end
117
+ super(message)
95
118
  end
96
119
  end
97
120
  end
@@ -36,6 +36,10 @@ module GraphQL
36
36
  @storage.compute_if_absent(value.class) { find_superclass_method(value.class) }
37
37
  end
38
38
 
39
+ def each
40
+ @storage.each_pair { |k, v| yield(k, v) }
41
+ end
42
+
39
43
  protected
40
44
 
41
45
  attr_reader :storage
@@ -48,7 +48,11 @@ module GraphQL
48
48
  end
49
49
  end
50
50
 
51
- if @value.is_a?(StandardError)
51
+ # `SKIP` was made into a subclass of `GraphQL::Error` to improve runtime performance
52
+ # (fewer clauses in a hot `case` block), but now it requires special handling here.
53
+ # I think it's still worth it for the performance win, but if the number of special
54
+ # cases grows, then maybe it's worth rethinking somehow.
55
+ if @value.is_a?(StandardError) && @value != GraphQL::Execution::Execute::SKIP
52
56
  raise @value
53
57
  else
54
58
  @value
@@ -51,7 +51,17 @@ module GraphQL
51
51
 
52
52
  # @return [Hash<Symbol, Object>]
53
53
  def arguments
54
- @arguments ||= @field && ArgumentHelpers.arguments(@query, nil, @field, ast_nodes.first)
54
+ if defined?(@arguments)
55
+ @arguments
56
+ else
57
+ @arguments = if @field
58
+ @query.schema.after_lazy(@query.arguments_for(@ast_nodes.first, @field)) do |args|
59
+ args.is_a?(Execution::Interpreter::Arguments) ? args.keyword_arguments : args
60
+ end
61
+ else
62
+ nil
63
+ end
64
+ end
55
65
  end
56
66
 
57
67
  # True if this node has a selection on `field_name`.
@@ -81,7 +91,7 @@ module GraphQL
81
91
  def selection(field_name, selected_type: @selected_type, arguments: nil)
82
92
  next_field_name = normalize_name(field_name)
83
93
 
84
- next_field_defn = FieldHelpers.get_field(@query.schema, selected_type, next_field_name)
94
+ next_field_defn = get_class_based_field(selected_type, next_field_name)
85
95
  if next_field_defn
86
96
  next_nodes = []
87
97
  @ast_nodes.each do |ast_node|
@@ -127,7 +137,7 @@ module GraphQL
127
137
 
128
138
  subselections_by_type.each do |type, ast_nodes_by_response_key|
129
139
  ast_nodes_by_response_key.each do |response_key, ast_nodes|
130
- field_defn = FieldHelpers.get_field(@query.schema, type, ast_nodes.first.name)
140
+ field_defn = get_class_based_field(type, ast_nodes.first.name)
131
141
  lookahead = Lookahead.new(query: @query, ast_nodes: ast_nodes, field: field_defn, owner_type: type)
132
142
  subselections.push(lookahead)
133
143
  end
@@ -203,8 +213,29 @@ module GraphQL
203
213
  end
204
214
  end
205
215
 
216
+ # Wrap get_field and ensure that it returns a GraphQL::Schema::Field.
217
+ # Remove this when legacy execution is removed.
218
+ def get_class_based_field(type, name)
219
+ f = @query.get_field(type, name)
220
+ f && f.type_class
221
+ end
222
+
223
+ def skipped_by_directive?(ast_selection)
224
+ ast_selection.directives.each do |directive|
225
+ dir_defn = @query.schema.directives.fetch(directive.name)
226
+ directive_class = dir_defn.type_class
227
+ if directive_class
228
+ dir_args = @query.arguments_for(directive, dir_defn)
229
+ return true unless directive_class.static_include?(dir_args, @query.context)
230
+ end
231
+ end
232
+ false
233
+ end
234
+
206
235
  def find_selections(subselections_by_type, selections_on_type, selected_type, ast_selections, arguments)
207
236
  ast_selections.each do |ast_selection|
237
+ next if skipped_by_directive?(ast_selection)
238
+
208
239
  case ast_selection
209
240
  when GraphQL::Language::Nodes::Field
210
241
  response_key = ast_selection.alias || ast_selection.name
@@ -213,7 +244,7 @@ module GraphQL
213
244
  elsif arguments.nil? || arguments.empty?
214
245
  selections_on_type[response_key] = [ast_selection]
215
246
  else
216
- field_defn = FieldHelpers.get_field(@query.schema, selected_type, ast_selection.name)
247
+ field_defn = get_class_based_field(selected_type, ast_selection.name)
217
248
  if arguments_match?(arguments, field_defn, ast_selection)
218
249
  selections_on_type[response_key] = [ast_selection]
219
250
  end
@@ -223,14 +254,14 @@ module GraphQL
223
254
  subselections_on_type = selections_on_type
224
255
  if (t = ast_selection.type)
225
256
  # Assuming this is valid, that `t` will be found.
226
- on_type = @query.schema.types[t.name].metadata[:type_class]
257
+ on_type = @query.get_type(t.name).type_class
227
258
  subselections_on_type = subselections_by_type[on_type] ||= {}
228
259
  end
229
260
  find_selections(subselections_by_type, subselections_on_type, on_type, ast_selection.selections, arguments)
230
261
  when GraphQL::Language::Nodes::FragmentSpread
231
262
  frag_defn = @query.fragments[ast_selection.name] || raise("Invariant: Can't look ahead to nonexistent fragment #{ast_selection.name} (found: #{@query.fragments.keys})")
232
263
  # Again, assuming a valid AST
233
- on_type = @query.schema.types[frag_defn.type.name].metadata[:type_class]
264
+ on_type = @query.get_type(frag_defn.type.name).type_class
234
265
  subselections_on_type = subselections_by_type[on_type] ||= {}
235
266
  find_selections(subselections_by_type, subselections_on_type, on_type, frag_defn.selections, arguments)
236
267
  else
@@ -242,6 +273,7 @@ module GraphQL
242
273
  # If a selection on `node` matches `field_name` (which is backed by `field_defn`)
243
274
  # and matches the `arguments:` constraints, then add that node to `matches`
244
275
  def find_selected_nodes(node, field_name, field_defn, arguments:, matches:)
276
+ return if skipped_by_directive?(node)
245
277
  case node
246
278
  when GraphQL::Language::Nodes::Field
247
279
  if node.name == field_name
@@ -263,120 +295,13 @@ module GraphQL
263
295
  end
264
296
 
265
297
  def arguments_match?(arguments, field_defn, field_node)
266
- query_kwargs = ArgumentHelpers.arguments(@query, nil, field_defn, field_node)
298
+ query_kwargs = @query.arguments_for(field_node, field_defn)
267
299
  arguments.all? do |arg_name, arg_value|
268
300
  arg_name = normalize_keyword(arg_name)
269
301
  # Make sure the constraint is present with a matching value
270
302
  query_kwargs.key?(arg_name) && query_kwargs[arg_name] == arg_value
271
303
  end
272
304
  end
273
-
274
- # TODO Dedup with interpreter
275
- module ArgumentHelpers
276
- module_function
277
-
278
- def arguments(query, graphql_object, arg_owner, ast_node)
279
- kwarg_arguments = {}
280
- arg_defns = arg_owner.arguments
281
- ast_node.arguments.each do |arg|
282
- arg_defn = arg_defns[arg.name] || raise("Invariant: missing argument definition for #{arg.name.inspect} in #{arg_defns.keys} from #{arg_owner}")
283
- # Need to distinguish between client-provided `nil`
284
- # and nothing-at-all
285
- is_present, value = arg_to_value(query, graphql_object, arg_defn.type, arg.value)
286
- if is_present
287
- # This doesn't apply to directives, which are legacy
288
- # Can remove this when Skip and Include use classes or something.
289
- if graphql_object
290
- value = arg_defn.prepare_value(graphql_object, value)
291
- end
292
- kwarg_arguments[arg_defn.keyword] = value
293
- end
294
- end
295
- arg_defns.each do |name, arg_defn|
296
- if arg_defn.default_value? && !kwarg_arguments.key?(arg_defn.keyword)
297
- kwarg_arguments[arg_defn.keyword] = arg_defn.default_value
298
- end
299
- end
300
- kwarg_arguments
301
- end
302
-
303
- # Get a Ruby-ready value from a client query.
304
- # @param graphql_object [Object] The owner of the field whose argument this is
305
- # @param arg_type [Class, GraphQL::Schema::NonNull, GraphQL::Schema::List]
306
- # @param ast_value [GraphQL::Language::Nodes::VariableIdentifier, String, Integer, Float, Boolean]
307
- # @return [Array(is_present, value)]
308
- def arg_to_value(query, graphql_object, arg_type, ast_value)
309
- if ast_value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
310
- # If it's not here, it will get added later
311
- if query.variables.key?(ast_value.name)
312
- return true, query.variables[ast_value.name]
313
- else
314
- return false, nil
315
- end
316
- elsif ast_value.is_a?(GraphQL::Language::Nodes::NullValue)
317
- return true, nil
318
- elsif arg_type.is_a?(GraphQL::Schema::NonNull)
319
- arg_to_value(query, graphql_object, arg_type.of_type, ast_value)
320
- elsif arg_type.is_a?(GraphQL::Schema::List)
321
- # Treat a single value like a list
322
- arg_value = Array(ast_value)
323
- list = []
324
- arg_value.map do |inner_v|
325
- _present, value = arg_to_value(query, graphql_object, arg_type.of_type, inner_v)
326
- list << value
327
- end
328
- return true, list
329
- elsif arg_type.is_a?(Class) && arg_type < GraphQL::Schema::InputObject
330
- # For these, `prepare` is applied during `#initialize`.
331
- # Pass `nil` so it will be skipped in `#arguments`.
332
- # What a mess.
333
- args = arguments(query, nil, arg_type, ast_value)
334
- # We're not tracking defaults_used, but for our purposes
335
- # we compare the value to the default value.
336
- return true, arg_type.new(ruby_kwargs: args, context: query.context, defaults_used: nil)
337
- else
338
- flat_value = flatten_ast_value(query, ast_value)
339
- return true, arg_type.coerce_input(flat_value, query.context)
340
- end
341
- end
342
-
343
- def flatten_ast_value(query, v)
344
- case v
345
- when GraphQL::Language::Nodes::Enum
346
- v.name
347
- when GraphQL::Language::Nodes::InputObject
348
- h = {}
349
- v.arguments.each do |arg|
350
- h[arg.name] = flatten_ast_value(query, arg.value)
351
- end
352
- h
353
- when Array
354
- v.map { |v2| flatten_ast_value(query, v2) }
355
- when GraphQL::Language::Nodes::VariableIdentifier
356
- flatten_ast_value(query.variables[v.name])
357
- else
358
- v
359
- end
360
- end
361
- end
362
-
363
- # TODO dedup with interpreter
364
- module FieldHelpers
365
- module_function
366
-
367
- def get_field(schema, owner_type, field_name)
368
- field_defn = owner_type.get_field(field_name)
369
- field_defn ||= if owner_type == schema.query.metadata[:type_class] && (entry_point_field = schema.introspection_system.entry_point(name: field_name))
370
- entry_point_field.metadata[:type_class]
371
- elsif (dynamic_field = schema.introspection_system.dynamic_field(name: field_name))
372
- dynamic_field.metadata[:type_class]
373
- else
374
- nil
375
- end
376
-
377
- field_defn
378
- end
379
- end
380
305
  end
381
306
  end
382
307
  end
@@ -29,13 +29,14 @@ module GraphQL
29
29
 
30
30
  include Tracing::Traceable
31
31
 
32
- attr_reader :context, :queries, :schema, :max_complexity
32
+ attr_reader :context, :queries, :schema, :max_complexity, :dataloader
33
33
  def initialize(schema:, queries:, context:, max_complexity:)
34
34
  @schema = schema
35
35
  @queries = queries
36
+ @queries.each { |q| q.multiplex = self }
36
37
  @context = context
37
- # TODO remove support for global tracers
38
- @tracers = schema.tracers + GraphQL::Tracing.tracers + (context[:tracers] || [])
38
+ @dataloader = @context[:dataloader] ||= @schema.dataloader_class.new
39
+ @tracers = schema.tracers + (context[:tracers] || [])
39
40
  # Support `context: {backtrace: true}`
40
41
  if context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
41
42
  @tracers << GraphQL::Backtrace::Tracer
@@ -73,6 +74,24 @@ module GraphQL
73
74
  end
74
75
  end
75
76
 
77
+ # @param query [GraphQL::Query]
78
+ def begin_query(results, idx, query, multiplex)
79
+ operation = query.selected_operation
80
+ result = if operation.nil? || !query.valid? || query.context.errors.any?
81
+ NO_OPERATION
82
+ else
83
+ begin
84
+ # These were checked to be the same in `#supports_multiplexing?`
85
+ query.schema.query_execution_strategy.begin_query(query, multiplex)
86
+ rescue GraphQL::ExecutionError => err
87
+ query.context.errors << err
88
+ NO_OPERATION
89
+ end
90
+ end
91
+ results[idx] = result
92
+ nil
93
+ end
94
+
76
95
  private
77
96
 
78
97
  def run_as_multiplex(multiplex)
@@ -80,43 +99,35 @@ module GraphQL
80
99
  multiplex.schema.query_execution_strategy.begin_multiplex(multiplex)
81
100
  queries = multiplex.queries
82
101
  # Do as much eager evaluation of the query as possible
83
- results = queries.map do |query|
84
- begin_query(query, multiplex)
102
+ results = []
103
+ queries.each_with_index do |query, idx|
104
+ multiplex.dataloader.append_job { begin_query(results, idx, query, multiplex) }
85
105
  end
86
106
 
107
+ multiplex.dataloader.run
108
+
87
109
  # Then, work through lazy results in a breadth-first way
88
- multiplex.schema.query_execution_strategy.finish_multiplex(results, multiplex)
110
+ multiplex.dataloader.append_job {
111
+ multiplex.schema.query_execution_strategy.finish_multiplex(results, multiplex)
112
+ }
113
+ multiplex.dataloader.run
89
114
 
90
115
  # Then, find all errors and assign the result to the query object
91
- results.each_with_index.map do |data_result, idx|
116
+ results.each_with_index do |data_result, idx|
92
117
  query = queries[idx]
93
118
  finish_query(data_result, query, multiplex)
94
119
  # Get the Query::Result, not the Hash
95
- query.result
120
+ results[idx] = query.result
96
121
  end
122
+
123
+ results
97
124
  rescue Exception
125
+ # TODO rescue at a higher level so it will catch errors in analysis, too
98
126
  # Assign values here so that the query's `@executed` becomes true
99
127
  queries.map { |q| q.result_values ||= {} }
100
128
  raise
101
129
  end
102
130
 
103
- # @param query [GraphQL::Query]
104
- # @return [Hash] The initial result (may not be finished if there are lazy values)
105
- def begin_query(query, multiplex)
106
- operation = query.selected_operation
107
- if operation.nil? || !query.valid? || query.context.errors.any?
108
- NO_OPERATION
109
- else
110
- begin
111
- # These were checked to be the same in `#supports_multiplexing?`
112
- query.schema.query_execution_strategy.begin_query(query, multiplex)
113
- rescue GraphQL::ExecutionError => err
114
- query.context.errors << err
115
- NO_OPERATION
116
- end
117
- end
118
- end
119
-
120
131
  # @param data_result [Hash] The result for the "data" key, if any
121
132
  # @param query [GraphQL::Query] The query which was run
122
133
  # @return [Hash] final result of this query, including all values and errors
@@ -140,10 +151,15 @@ module GraphQL
140
151
 
141
152
  result
142
153
  end
154
+ if query.context.namespace?(:__query_result_extensions__)
155
+ query.result_values["extensions"] = query.context.namespace(:__query_result_extensions__)
156
+ end
143
157
  end
144
158
 
145
159
  # use the old `query_execution_strategy` etc to run this query
146
160
  def run_one_legacy(schema, query)
161
+ GraphQL::Deprecation.warn "Multiplex.run_one_legacy will be removed from GraphQL-Ruby 2.0, upgrade to the Interpreter to avoid this deprecated codepath: https://graphql-ruby.org/queries/interpreter.html"
162
+
147
163
  query.result_values = if !query.valid?
148
164
  all_errors = query.validation_errors + query.analysis_errors + query.context.errors
149
165
  if all_errors.any?
@@ -173,6 +189,15 @@ module GraphQL
173
189
  def instrument_and_analyze(multiplex)
174
190
  GraphQL::Execution::Instrumentation.apply_instrumenters(multiplex) do
175
191
  schema = multiplex.schema
192
+ if schema.interpreter? && schema.analysis_engine != GraphQL::Analysis::AST
193
+ raise <<-ERR
194
+ Can't use `GraphQL::Execution::Interpreter` without `GraphQL::Analysis::AST`, please add this plugin to your schema:
195
+
196
+ use GraphQL::Analysis::AST
197
+
198
+ For information about the new analysis engine: https://graphql-ruby.org/queries/ast_analysis.html
199
+ ERR
200
+ end
176
201
  multiplex_analyzers = schema.multiplex_analyzers
177
202
  if multiplex.max_complexity
178
203
  multiplex_analyzers += if schema.using_ast_analysis?
data/lib/graphql/field.rb CHANGED
@@ -2,126 +2,10 @@
2
2
  require "graphql/field/resolve"
3
3
 
4
4
  module GraphQL
5
- # {Field}s belong to {ObjectType}s and {InterfaceType}s.
6
- #
7
- # They're usually created with the `field` helper. If you create it by hand, make sure {#name} is a String.
8
- #
9
- # A field must have a return type, but if you want to defer the return type calculation until later,
10
- # you can pass a proc for the return type. That proc will be called when the schema is defined.
11
- #
12
- # @example Lazy type resolution
13
- # # If the field's type isn't defined yet, you can pass a proc
14
- # field :city, -> { TypeForModelName.find("City") }
15
- #
16
- # For complex field definition, you can pass a block to the `field` helper, eg `field :name do ... end`.
17
- # This block is equivalent to calling `GraphQL::Field.define { ... }`.
18
- #
19
- # @example Defining a field with a block
20
- # field :city, CityType do
21
- # # field definition continues inside the block
22
- # end
23
- #
24
- # ## Resolve
25
- #
26
- # Fields have `resolve` functions to determine their values at query-time.
27
- # The default implementation is to call a method on the object based on the field name.
28
- #
29
- # @example Create a field which calls a method with the same name.
30
- # GraphQL::ObjectType.define do
31
- # field :name, types.String, "The name of this thing "
32
- # end
33
- #
34
- # You can specify a custom proc with the `resolve` helper.
35
- #
36
- # There are some shortcuts for common `resolve` implementations:
37
- # - Provide `property:` to call a method with a different name than the field name
38
- # - Provide `hash_key:` to resolve the field by doing a key lookup, eg `obj[:my_hash_key]`
39
- #
40
- # @example Create a field that calls a different method on the object
41
- # GraphQL::ObjectType.define do
42
- # # use the `property` keyword:
43
- # field :firstName, types.String, property: :first_name
44
- # end
45
- #
46
- # @example Create a field looks up with `[hash_key]`
47
- # GraphQL::ObjectType.define do
48
- # # use the `hash_key` keyword:
49
- # field :firstName, types.String, hash_key: :first_name
50
- # end
51
- #
52
- # ## Arguments
53
- #
54
- # Fields can take inputs; they're called arguments. You can define them with the `argument` helper.
55
- #
56
- # @example Create a field with an argument
57
- # field :students, types[StudentType] do
58
- # argument :grade, types.Int
59
- # resolve ->(obj, args, ctx) {
60
- # Student.where(grade: args[:grade])
61
- # }
62
- # end
63
- #
64
- # They can have default values which will be provided to `resolve` if the query doesn't include a value.
65
- #
66
- # @example Argument with a default value
67
- # field :events, types[EventType] do
68
- # # by default, don't include past events
69
- # argument :includePast, types.Boolean, default_value: false
70
- # resolve ->(obj, args, ctx) {
71
- # args[:includePast] # => false if no value was provided in the query
72
- # # ...
73
- # }
74
- # end
75
- #
76
- # Only certain types maybe used for inputs:
77
- #
78
- # - Scalars
79
- # - Enums
80
- # - Input Objects
81
- # - Lists of those types
82
- #
83
- # Input types may also be non-null -- in that case, the query will fail
84
- # if the input is not present.
85
- #
86
- # ## Complexity
87
- #
88
- # Fields can have _complexity_ values which describe the computation cost of resolving the field.
89
- # You can provide the complexity as a constant with `complexity:` or as a proc, with the `complexity` helper.
90
- #
91
- # @example Custom complexity values
92
- # # Complexity can be a number or a proc.
93
- #
94
- # # Complexity can be defined with a keyword:
95
- # field :expensive_calculation, !types.Int, complexity: 10
96
- #
97
- # # Or inside the block:
98
- # field :expensive_calculation_2, !types.Int do
99
- # complexity ->(ctx, args, child_complexity) { ctx[:current_user].staff? ? 0 : 10 }
100
- # end
101
- #
102
- # @example Calculating the complexity of a list field
103
- # field :items, types[ItemType] do
104
- # argument :limit, !types.Int
105
- # # Multiply the child complexity by the possible items on the list
106
- # complexity ->(ctx, args, child_complexity) { child_complexity * args[:limit] }
107
- # end
108
- #
109
- # @example Creating a field, then assigning it to a type
110
- # name_field = GraphQL::Field.define do
111
- # name("Name")
112
- # type(!types.String)
113
- # description("The name of this thing")
114
- # resolve ->(object, arguments, context) { object.name }
115
- # end
116
- #
117
- # NamedType = GraphQL::ObjectType.define do
118
- # # The second argument may be a GraphQL::Field
119
- # field :name, name_field
120
- # end
121
- #
5
+ # @api deprecated
122
6
  class Field
123
7
  include GraphQL::Define::InstanceDefinable
124
- accepts_definitions :name, :description, :deprecation_reason,
8
+ deprecated_accepts_definitions :name, :description, :deprecation_reason,
125
9
  :resolve, :lazy_resolve,
126
10
  :type, :arguments,
127
11
  :property, :hash_key, :complexity,
@@ -196,6 +80,10 @@ module GraphQL
196
80
 
197
81
  attr_accessor :ast_node
198
82
 
83
+ # Future-compatible alias
84
+ # @see {GraphQL::SchemaMember}
85
+ alias :graphql_definition :itself
86
+
199
87
  # @return [Boolean]
200
88
  def connection?
201
89
  @connection
@@ -266,7 +154,7 @@ module GraphQL
266
154
  end
267
155
 
268
156
  def name=(new_name)
269
- old_name = @name
157
+ old_name = defined?(@name) ? @name : nil
270
158
  @name = new_name
271
159
 
272
160
  if old_name != new_name && @resolve_proc.is_a?(Field::Resolve::NameResolve)
@@ -315,6 +203,14 @@ module GraphQL
315
203
  }
316
204
  end
317
205
 
206
+ def type_class
207
+ metadata[:type_class]
208
+ end
209
+
210
+ def get_argument(argument_name)
211
+ arguments[argument_name]
212
+ end
213
+
318
214
  private
319
215
 
320
216
  def build_default_resolver
@@ -33,7 +33,7 @@ module GraphQL
33
33
  end
34
34
 
35
35
  def self.build(onlies)
36
- case onlies
36
+ case onlies.size
37
37
  when 0
38
38
  nil
39
39
  when 1
@@ -1,2 +1,2 @@
1
1
  # frozen_string_literal: true
2
- GraphQL::FLOAT_TYPE = GraphQL::Types::Float.graphql_definition
2
+ GraphQL::FLOAT_TYPE = GraphQL::Types::Float.graphql_definition(silence_deprecation_warning: true)