graphql 0.16.0 → 2.0.15

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 (490) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +5 -0
  3. data/lib/generators/graphql/core.rb +69 -0
  4. data/lib/generators/graphql/enum_generator.rb +27 -0
  5. data/lib/generators/graphql/field_extractor.rb +31 -0
  6. data/lib/generators/graphql/input_generator.rb +50 -0
  7. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  8. data/lib/generators/graphql/install/templates/base_mutation.erb +10 -0
  9. data/lib/generators/graphql/install/templates/mutation_type.erb +12 -0
  10. data/lib/generators/graphql/install_generator.rb +197 -0
  11. data/lib/generators/graphql/interface_generator.rb +27 -0
  12. data/lib/generators/graphql/loader_generator.rb +21 -0
  13. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  14. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  15. data/lib/generators/graphql/mutation_generator.rb +30 -0
  16. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  17. data/lib/generators/graphql/object_generator.rb +50 -0
  18. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  19. data/lib/generators/graphql/relay.rb +49 -0
  20. data/lib/generators/graphql/relay_generator.rb +21 -0
  21. data/lib/generators/graphql/scalar_generator.rb +22 -0
  22. data/lib/generators/graphql/templates/base_argument.erb +6 -0
  23. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  24. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  25. data/lib/generators/graphql/templates/base_enum.erb +6 -0
  26. data/lib/generators/graphql/templates/base_field.erb +7 -0
  27. data/lib/generators/graphql/templates/base_input_object.erb +7 -0
  28. data/lib/generators/graphql/templates/base_interface.erb +9 -0
  29. data/lib/generators/graphql/templates/base_object.erb +7 -0
  30. data/lib/generators/graphql/templates/base_scalar.erb +6 -0
  31. data/lib/generators/graphql/templates/base_union.erb +6 -0
  32. data/lib/generators/graphql/templates/enum.erb +11 -0
  33. data/lib/generators/graphql/templates/graphql_controller.erb +52 -0
  34. data/lib/generators/graphql/templates/input.erb +9 -0
  35. data/lib/generators/graphql/templates/interface.erb +10 -0
  36. data/lib/generators/graphql/templates/loader.erb +19 -0
  37. data/lib/generators/graphql/templates/mutation.erb +16 -0
  38. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  39. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  40. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  41. data/lib/generators/graphql/templates/node_type.erb +9 -0
  42. data/lib/generators/graphql/templates/object.erb +10 -0
  43. data/lib/generators/graphql/templates/query_type.erb +15 -0
  44. data/lib/generators/graphql/templates/scalar.erb +17 -0
  45. data/lib/generators/graphql/templates/schema.erb +30 -0
  46. data/lib/generators/graphql/templates/union.erb +9 -0
  47. data/lib/generators/graphql/type_generator.rb +135 -0
  48. data/lib/generators/graphql/union_generator.rb +33 -0
  49. data/lib/graphql/analysis/ast/analyzer.rb +84 -0
  50. data/lib/graphql/analysis/ast/field_usage.rb +57 -0
  51. data/lib/graphql/analysis/ast/max_query_complexity.rb +22 -0
  52. data/lib/graphql/analysis/ast/max_query_depth.rb +22 -0
  53. data/lib/graphql/analysis/ast/query_complexity.rb +230 -0
  54. data/lib/graphql/analysis/ast/query_depth.rb +55 -0
  55. data/lib/graphql/analysis/ast/visitor.rb +269 -0
  56. data/lib/graphql/analysis/ast.rb +81 -0
  57. data/lib/graphql/analysis.rb +2 -5
  58. data/lib/graphql/analysis_error.rb +1 -0
  59. data/lib/graphql/backtrace/inspect_result.rb +50 -0
  60. data/lib/graphql/backtrace/table.rb +141 -0
  61. data/lib/graphql/backtrace/traced_error.rb +54 -0
  62. data/lib/graphql/backtrace/tracer.rb +80 -0
  63. data/lib/graphql/backtrace.rb +58 -0
  64. data/lib/graphql/coercion_error.rb +13 -0
  65. data/lib/graphql/dataloader/null_dataloader.rb +24 -0
  66. data/lib/graphql/dataloader/request.rb +19 -0
  67. data/lib/graphql/dataloader/request_all.rb +19 -0
  68. data/lib/graphql/dataloader/source.rb +164 -0
  69. data/lib/graphql/dataloader.rb +311 -0
  70. data/lib/graphql/date_encoding_error.rb +16 -0
  71. data/lib/graphql/deprecation.rb +9 -0
  72. data/lib/graphql/dig.rb +19 -0
  73. data/lib/graphql/execution/directive_checks.rb +37 -0
  74. data/lib/graphql/execution/errors.rb +93 -0
  75. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  76. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  77. data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
  78. data/lib/graphql/execution/interpreter/execution_errors.rb +29 -0
  79. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  80. data/lib/graphql/execution/interpreter/resolve.rb +77 -0
  81. data/lib/graphql/execution/interpreter/runtime.rb +994 -0
  82. data/lib/graphql/execution/interpreter.rb +226 -0
  83. data/lib/graphql/execution/lazy/lazy_method_map.rb +98 -0
  84. data/lib/graphql/execution/lazy.rb +75 -0
  85. data/lib/graphql/execution/lookahead.rb +311 -0
  86. data/lib/graphql/execution/multiplex.rb +45 -0
  87. data/lib/graphql/execution.rb +18 -0
  88. data/lib/graphql/execution_error.rb +34 -1
  89. data/lib/graphql/filter.rb +53 -0
  90. data/lib/graphql/integer_decoding_error.rb +17 -0
  91. data/lib/graphql/integer_encoding_error.rb +36 -0
  92. data/lib/graphql/introspection/base_object.rb +13 -0
  93. data/lib/graphql/introspection/directive_location_enum.rb +12 -5
  94. data/lib/graphql/introspection/directive_type.rb +30 -10
  95. data/lib/graphql/introspection/dynamic_fields.rb +12 -0
  96. data/lib/graphql/introspection/entry_points.rb +22 -0
  97. data/lib/graphql/introspection/enum_value_type.rb +21 -8
  98. data/lib/graphql/introspection/field_type.rb +26 -10
  99. data/lib/graphql/introspection/input_value_type.rb +64 -14
  100. data/lib/graphql/introspection/introspection_query.rb +7 -76
  101. data/lib/graphql/introspection/schema_type.rb +42 -17
  102. data/lib/graphql/introspection/type_kind_enum.rb +11 -5
  103. data/lib/graphql/introspection/type_type.rb +104 -16
  104. data/lib/graphql/introspection.rb +104 -13
  105. data/lib/graphql/invalid_name_error.rb +11 -0
  106. data/lib/graphql/invalid_null_error.rb +36 -8
  107. data/lib/graphql/language/block_string.rb +99 -0
  108. data/lib/graphql/language/cache.rb +37 -0
  109. data/lib/graphql/language/definition_slice.rb +41 -0
  110. data/lib/graphql/language/document_from_schema_definition.rb +335 -0
  111. data/lib/graphql/language/generation.rb +16 -86
  112. data/lib/graphql/language/lexer.rb +1436 -705
  113. data/lib/graphql/language/lexer.rl +172 -64
  114. data/lib/graphql/language/nodes.rb +617 -105
  115. data/lib/graphql/language/parser.rb +1524 -430
  116. data/lib/graphql/language/parser.y +348 -73
  117. data/lib/graphql/language/printer.rb +386 -0
  118. data/lib/graphql/language/sanitized_printer.rb +222 -0
  119. data/lib/graphql/language/token.rb +16 -3
  120. data/lib/graphql/language/visitor.rb +169 -25
  121. data/lib/graphql/language.rb +30 -0
  122. data/lib/graphql/load_application_object_failed_error.rb +22 -0
  123. data/lib/graphql/name_validator.rb +11 -0
  124. data/lib/graphql/pagination/active_record_relation_connection.rb +85 -0
  125. data/lib/graphql/pagination/array_connection.rb +79 -0
  126. data/lib/graphql/pagination/connection.rb +253 -0
  127. data/lib/graphql/pagination/connections.rb +135 -0
  128. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  129. data/lib/graphql/pagination/relation_connection.rb +228 -0
  130. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  131. data/lib/graphql/pagination.rb +6 -0
  132. data/lib/graphql/parse_error.rb +24 -0
  133. data/lib/graphql/query/context.rb +266 -12
  134. data/lib/graphql/query/fingerprint.rb +26 -0
  135. data/lib/graphql/query/input_validation_result.rb +34 -7
  136. data/lib/graphql/query/null_context.rb +52 -0
  137. data/lib/graphql/query/result.rb +63 -0
  138. data/lib/graphql/query/validation_pipeline.rb +114 -0
  139. data/lib/graphql/query/variable_validation_error.rb +27 -3
  140. data/lib/graphql/query/variables.rb +75 -24
  141. data/lib/graphql/query.rb +359 -92
  142. data/lib/graphql/railtie.rb +13 -0
  143. data/lib/graphql/rake_task/validate.rb +63 -0
  144. data/lib/graphql/rake_task.rb +146 -0
  145. data/lib/graphql/relay/range_add.rb +52 -0
  146. data/lib/graphql/relay.rb +3 -0
  147. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  148. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  149. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  150. data/lib/graphql/rubocop.rb +4 -0
  151. data/lib/graphql/runtime_type_error.rb +5 -0
  152. data/lib/graphql/schema/addition.rb +245 -0
  153. data/lib/graphql/schema/argument.rb +395 -0
  154. data/lib/graphql/schema/base_64_bp.rb +26 -0
  155. data/lib/graphql/schema/base_64_encoder.rb +21 -0
  156. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +47 -0
  157. data/lib/graphql/schema/build_from_definition/resolve_map.rb +78 -0
  158. data/lib/graphql/schema/build_from_definition.rb +492 -0
  159. data/lib/graphql/schema/built_in_types.rb +12 -0
  160. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  161. data/lib/graphql/schema/directive/feature.rb +66 -0
  162. data/lib/graphql/schema/directive/flagged.rb +57 -0
  163. data/lib/graphql/schema/directive/include.rb +25 -0
  164. data/lib/graphql/schema/directive/one_of.rb +12 -0
  165. data/lib/graphql/schema/directive/skip.rb +25 -0
  166. data/lib/graphql/schema/directive/transform.rb +60 -0
  167. data/lib/graphql/schema/directive.rb +212 -0
  168. data/lib/graphql/schema/enum.rb +176 -0
  169. data/lib/graphql/schema/enum_value.rb +77 -0
  170. data/lib/graphql/schema/field/connection_extension.rb +80 -0
  171. data/lib/graphql/schema/field/scope_extension.rb +22 -0
  172. data/lib/graphql/schema/field.rb +862 -0
  173. data/lib/graphql/schema/field_extension.rb +156 -0
  174. data/lib/graphql/schema/find_inherited_value.rb +36 -0
  175. data/lib/graphql/schema/finder.rb +155 -0
  176. data/lib/graphql/schema/input_object.rb +258 -0
  177. data/lib/graphql/schema/interface.rb +113 -0
  178. data/lib/graphql/schema/introspection_system.rb +164 -0
  179. data/lib/graphql/schema/invalid_type_error.rb +1 -0
  180. data/lib/graphql/schema/late_bound_type.rb +37 -0
  181. data/lib/graphql/schema/list.rb +86 -0
  182. data/lib/graphql/schema/loader.rb +228 -0
  183. data/lib/graphql/schema/member/base_dsl_methods.rb +124 -0
  184. data/lib/graphql/schema/member/build_type.rb +178 -0
  185. data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
  186. data/lib/graphql/schema/member/has_arguments.rb +376 -0
  187. data/lib/graphql/schema/member/has_ast_node.rb +20 -0
  188. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  189. data/lib/graphql/schema/member/has_directives.rb +113 -0
  190. data/lib/graphql/schema/member/has_fields.rb +163 -0
  191. data/lib/graphql/schema/member/has_interfaces.rb +88 -0
  192. data/lib/graphql/schema/member/has_path.rb +25 -0
  193. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  194. data/lib/graphql/schema/member/has_validators.rb +31 -0
  195. data/lib/graphql/schema/member/relay_shortcuts.rb +73 -0
  196. data/lib/graphql/schema/member/scoped.rb +21 -0
  197. data/lib/graphql/schema/member/type_system_helpers.rb +38 -0
  198. data/lib/graphql/schema/member/validates_input.rb +33 -0
  199. data/lib/graphql/schema/member.rb +39 -0
  200. data/lib/graphql/schema/mutation.rb +85 -0
  201. data/lib/graphql/schema/non_null.rb +67 -0
  202. data/lib/graphql/schema/null_mask.rb +11 -0
  203. data/lib/graphql/schema/object.rb +117 -0
  204. data/lib/graphql/schema/printer.rb +72 -128
  205. data/lib/graphql/schema/relay_classic_mutation.rb +179 -0
  206. data/lib/graphql/schema/resolver/has_payload_type.rb +106 -0
  207. data/lib/graphql/schema/resolver.rb +402 -0
  208. data/lib/graphql/schema/scalar.rb +68 -0
  209. data/lib/graphql/schema/subscription.rb +148 -0
  210. data/lib/graphql/schema/timeout.rb +123 -0
  211. data/lib/graphql/schema/type_expression.rb +29 -5
  212. data/lib/graphql/schema/type_membership.rb +51 -0
  213. data/lib/graphql/schema/union.rb +81 -0
  214. data/lib/graphql/schema/unique_within_type.rb +34 -0
  215. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  216. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  217. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  218. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  219. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  220. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  221. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  222. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  223. data/lib/graphql/schema/validator.rb +171 -0
  224. data/lib/graphql/schema/warden.rb +413 -0
  225. data/lib/graphql/schema/wrapper.rb +24 -0
  226. data/lib/graphql/schema.rb +1179 -104
  227. data/lib/graphql/static_validation/all_rules.rb +14 -0
  228. data/lib/graphql/static_validation/base_visitor.rb +200 -0
  229. data/lib/graphql/static_validation/definition_dependencies.rb +198 -0
  230. data/lib/graphql/static_validation/error.rb +46 -0
  231. data/lib/graphql/static_validation/interpreter_visitor.rb +14 -0
  232. data/lib/graphql/static_validation/literal_validator.rb +113 -22
  233. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +59 -11
  234. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +48 -0
  235. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +31 -0
  236. data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +30 -0
  237. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +62 -8
  238. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +37 -0
  239. data/lib/graphql/static_validation/rules/directives_are_defined.rb +20 -13
  240. data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +29 -0
  241. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +32 -26
  242. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +31 -0
  243. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +21 -23
  244. data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +32 -0
  245. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +55 -18
  246. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +31 -0
  247. data/lib/graphql/static_validation/rules/fields_will_merge.rb +390 -70
  248. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +53 -0
  249. data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +30 -0
  250. data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +29 -0
  251. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +54 -37
  252. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +35 -0
  253. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +26 -16
  254. data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +29 -0
  255. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +13 -19
  256. data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +29 -0
  257. data/lib/graphql/static_validation/rules/fragments_are_named.rb +16 -0
  258. data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +26 -0
  259. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +25 -20
  260. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +30 -0
  261. data/lib/graphql/static_validation/rules/fragments_are_used.rb +22 -33
  262. data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +29 -0
  263. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  264. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  265. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +17 -0
  266. data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +26 -0
  267. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +41 -0
  268. data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +25 -0
  269. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  270. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  271. data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +36 -0
  272. data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +28 -0
  273. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  274. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  275. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +22 -21
  276. data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +35 -0
  277. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +59 -0
  278. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +35 -0
  279. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +17 -0
  280. data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +26 -0
  281. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +56 -0
  282. data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +29 -0
  283. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +36 -18
  284. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +39 -0
  285. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +24 -0
  286. data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +29 -0
  287. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +103 -39
  288. data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +38 -0
  289. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +22 -14
  290. data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +32 -0
  291. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +92 -70
  292. data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +37 -0
  293. data/lib/graphql/static_validation/type_stack.rb +85 -24
  294. data/lib/graphql/static_validation/validation_context.rb +25 -46
  295. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  296. data/lib/graphql/static_validation/validator.rb +46 -15
  297. data/lib/graphql/static_validation.rb +6 -3
  298. data/lib/graphql/string_encoding_error.rb +20 -0
  299. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +247 -0
  300. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  301. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +58 -0
  302. data/lib/graphql/subscriptions/event.rb +144 -0
  303. data/lib/graphql/subscriptions/instrumentation.rb +28 -0
  304. data/lib/graphql/subscriptions/serialize.rb +158 -0
  305. data/lib/graphql/subscriptions.rb +306 -0
  306. data/lib/graphql/tracing/active_support_notifications_tracing.rb +21 -0
  307. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  308. data/lib/graphql/tracing/appsignal_tracing.rb +51 -0
  309. data/lib/graphql/tracing/data_dog_tracing.rb +100 -0
  310. data/lib/graphql/tracing/instrumentation_tracing.rb +83 -0
  311. data/lib/graphql/tracing/new_relic_tracing.rb +51 -0
  312. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  313. data/lib/graphql/tracing/platform_tracing.rb +122 -0
  314. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +32 -0
  315. data/lib/graphql/tracing/prometheus_tracing.rb +67 -0
  316. data/lib/graphql/tracing/scout_tracing.rb +54 -0
  317. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  318. data/lib/graphql/tracing.rb +94 -0
  319. data/lib/graphql/type_kinds.rb +50 -22
  320. data/lib/graphql/types/big_int.rb +23 -0
  321. data/lib/graphql/types/boolean.rb +18 -0
  322. data/lib/graphql/types/float.rb +19 -0
  323. data/lib/graphql/types/id.rb +24 -0
  324. data/lib/graphql/types/int.rb +36 -0
  325. data/lib/graphql/types/iso_8601_date.rb +45 -0
  326. data/lib/graphql/types/iso_8601_date_time.rb +76 -0
  327. data/lib/graphql/types/json.rb +25 -0
  328. data/lib/graphql/types/relay/base_connection.rb +49 -0
  329. data/lib/graphql/types/relay/base_edge.rb +29 -0
  330. data/lib/graphql/types/relay/connection_behaviors.rb +154 -0
  331. data/lib/graphql/types/relay/default_relay.rb +21 -0
  332. data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
  333. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  334. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  335. data/lib/graphql/types/relay/node.rb +15 -0
  336. data/lib/graphql/types/relay/node_behaviors.rb +19 -0
  337. data/lib/graphql/types/relay/page_info.rb +11 -0
  338. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  339. data/lib/graphql/types/relay.rb +39 -0
  340. data/lib/graphql/types/string.rb +29 -0
  341. data/lib/graphql/types.rb +11 -0
  342. data/lib/graphql/unauthorized_error.rb +29 -0
  343. data/lib/graphql/unauthorized_field_error.rb +23 -0
  344. data/lib/graphql/unresolved_type_error.rb +35 -0
  345. data/lib/graphql/version.rb +2 -1
  346. data/lib/graphql.rb +86 -41
  347. data/readme.md +15 -101
  348. metadata +394 -279
  349. data/lib/graphql/analysis/analyze_query.rb +0 -73
  350. data/lib/graphql/analysis/max_query_complexity.rb +0 -25
  351. data/lib/graphql/analysis/max_query_depth.rb +0 -25
  352. data/lib/graphql/analysis/query_complexity.rb +0 -122
  353. data/lib/graphql/analysis/query_depth.rb +0 -54
  354. data/lib/graphql/argument.rb +0 -25
  355. data/lib/graphql/base_type.rb +0 -115
  356. data/lib/graphql/boolean_type.rb +0 -9
  357. data/lib/graphql/define/assign_argument.rb +0 -20
  358. data/lib/graphql/define/assign_enum_value.rb +0 -16
  359. data/lib/graphql/define/assign_object_field.rb +0 -21
  360. data/lib/graphql/define/assignment_dictionary.rb +0 -26
  361. data/lib/graphql/define/defined_object_proxy.rb +0 -32
  362. data/lib/graphql/define/instance_definable.rb +0 -79
  363. data/lib/graphql/define/non_null_with_bang.rb +0 -15
  364. data/lib/graphql/define/type_definer.rb +0 -30
  365. data/lib/graphql/define.rb +0 -8
  366. data/lib/graphql/directive/include_directive.rb +0 -10
  367. data/lib/graphql/directive/skip_directive.rb +0 -11
  368. data/lib/graphql/directive.rb +0 -49
  369. data/lib/graphql/enum_type.rb +0 -95
  370. data/lib/graphql/field.rb +0 -131
  371. data/lib/graphql/float_type.rb +0 -5
  372. data/lib/graphql/id_type.rb +0 -12
  373. data/lib/graphql/input_object_type.rb +0 -71
  374. data/lib/graphql/int_type.rb +0 -5
  375. data/lib/graphql/interface_type.rb +0 -38
  376. data/lib/graphql/internal_representation/node.rb +0 -81
  377. data/lib/graphql/internal_representation/rewrite.rb +0 -177
  378. data/lib/graphql/internal_representation.rb +0 -2
  379. data/lib/graphql/introspection/arguments_field.rb +0 -5
  380. data/lib/graphql/introspection/enum_values_field.rb +0 -13
  381. data/lib/graphql/introspection/fields_field.rb +0 -13
  382. data/lib/graphql/introspection/input_fields_field.rb +0 -12
  383. data/lib/graphql/introspection/interfaces_field.rb +0 -5
  384. data/lib/graphql/introspection/of_type_field.rb +0 -6
  385. data/lib/graphql/introspection/possible_types_field.rb +0 -11
  386. data/lib/graphql/introspection/schema_field.rb +0 -15
  387. data/lib/graphql/introspection/type_by_name_field.rb +0 -16
  388. data/lib/graphql/introspection/typename_field.rb +0 -15
  389. data/lib/graphql/list_type.rb +0 -46
  390. data/lib/graphql/non_null_type.rb +0 -43
  391. data/lib/graphql/object_type.rb +0 -93
  392. data/lib/graphql/query/arguments.rb +0 -76
  393. data/lib/graphql/query/directive_resolution.rb +0 -16
  394. data/lib/graphql/query/executor.rb +0 -45
  395. data/lib/graphql/query/literal_input.rb +0 -90
  396. data/lib/graphql/query/serial_execution/execution_context.rb +0 -31
  397. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -82
  398. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -27
  399. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -42
  400. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -107
  401. data/lib/graphql/query/serial_execution.rb +0 -41
  402. data/lib/graphql/query/type_resolver.rb +0 -25
  403. data/lib/graphql/scalar_type.rb +0 -53
  404. data/lib/graphql/schema/catchall_middleware.rb +0 -34
  405. data/lib/graphql/schema/middleware_chain.rb +0 -28
  406. data/lib/graphql/schema/possible_types.rb +0 -34
  407. data/lib/graphql/schema/reduce_types.rb +0 -68
  408. data/lib/graphql/schema/rescue_middleware.rb +0 -53
  409. data/lib/graphql/schema/timeout_middleware.rb +0 -67
  410. data/lib/graphql/schema/type_map.rb +0 -30
  411. data/lib/graphql/schema/validation.rb +0 -164
  412. data/lib/graphql/static_validation/arguments_validator.rb +0 -48
  413. data/lib/graphql/static_validation/message.rb +0 -36
  414. data/lib/graphql/string_type.rb +0 -5
  415. data/lib/graphql/union_type.rb +0 -38
  416. data/spec/graphql/analysis/analyze_query_spec.rb +0 -50
  417. data/spec/graphql/analysis/max_query_complexity_spec.rb +0 -62
  418. data/spec/graphql/analysis/max_query_depth_spec.rb +0 -100
  419. data/spec/graphql/analysis/query_complexity_spec.rb +0 -235
  420. data/spec/graphql/analysis/query_depth_spec.rb +0 -80
  421. data/spec/graphql/argument_spec.rb +0 -20
  422. data/spec/graphql/base_type_spec.rb +0 -24
  423. data/spec/graphql/boolean_type_spec.rb +0 -20
  424. data/spec/graphql/define/instance_definable_spec.rb +0 -55
  425. data/spec/graphql/directive_spec.rb +0 -77
  426. data/spec/graphql/enum_type_spec.rb +0 -31
  427. data/spec/graphql/execution_error_spec.rb +0 -61
  428. data/spec/graphql/field_spec.rb +0 -92
  429. data/spec/graphql/float_type_spec.rb +0 -15
  430. data/spec/graphql/id_type_spec.rb +0 -32
  431. data/spec/graphql/input_object_type_spec.rb +0 -162
  432. data/spec/graphql/int_type_spec.rb +0 -15
  433. data/spec/graphql/interface_type_spec.rb +0 -56
  434. data/spec/graphql/internal_representation/rewrite_spec.rb +0 -120
  435. data/spec/graphql/introspection/directive_type_spec.rb +0 -50
  436. data/spec/graphql/introspection/input_value_type_spec.rb +0 -42
  437. data/spec/graphql/introspection/introspection_query_spec.rb +0 -10
  438. data/spec/graphql/introspection/schema_type_spec.rb +0 -45
  439. data/spec/graphql/introspection/type_type_spec.rb +0 -122
  440. data/spec/graphql/language/generation_spec.rb +0 -42
  441. data/spec/graphql/language/parser_spec.rb +0 -442
  442. data/spec/graphql/language/visitor_spec.rb +0 -49
  443. data/spec/graphql/list_type_spec.rb +0 -32
  444. data/spec/graphql/non_null_type_spec.rb +0 -31
  445. data/spec/graphql/object_type_spec.rb +0 -42
  446. data/spec/graphql/query/arguments_spec.rb +0 -25
  447. data/spec/graphql/query/context_spec.rb +0 -83
  448. data/spec/graphql/query/executor_spec.rb +0 -273
  449. data/spec/graphql/query/serial_execution/execution_context_spec.rb +0 -53
  450. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +0 -66
  451. data/spec/graphql/query/type_resolver_spec.rb +0 -8
  452. data/spec/graphql/query/variables_spec.rb +0 -28
  453. data/spec/graphql/query_spec.rb +0 -363
  454. data/spec/graphql/scalar_type_spec.rb +0 -61
  455. data/spec/graphql/schema/catchall_middleware_spec.rb +0 -32
  456. data/spec/graphql/schema/middleware_chain_spec.rb +0 -42
  457. data/spec/graphql/schema/printer_spec.rb +0 -190
  458. data/spec/graphql/schema/reduce_types_spec.rb +0 -102
  459. data/spec/graphql/schema/rescue_middleware_spec.rb +0 -33
  460. data/spec/graphql/schema/timeout_middleware_spec.rb +0 -180
  461. data/spec/graphql/schema/type_expression_spec.rb +0 -38
  462. data/spec/graphql/schema/validation_spec.rb +0 -219
  463. data/spec/graphql/schema_spec.rb +0 -23
  464. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +0 -63
  465. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +0 -48
  466. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +0 -34
  467. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +0 -39
  468. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +0 -60
  469. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +0 -31
  470. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +0 -48
  471. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +0 -47
  472. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +0 -39
  473. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +0 -44
  474. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +0 -49
  475. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +0 -25
  476. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +0 -42
  477. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +0 -44
  478. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +0 -63
  479. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +0 -37
  480. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +0 -53
  481. data/spec/graphql/static_validation/type_stack_spec.rb +0 -37
  482. data/spec/graphql/static_validation/validator_spec.rb +0 -69
  483. data/spec/graphql/string_type_spec.rb +0 -15
  484. data/spec/graphql/union_type_spec.rb +0 -31
  485. data/spec/spec_helper.rb +0 -18
  486. data/spec/support/dairy_app.rb +0 -309
  487. data/spec/support/dairy_data.rb +0 -23
  488. data/spec/support/minimum_input_object.rb +0 -16
  489. data/spec/support/star_wars_data.rb +0 -71
  490. data/spec/support/star_wars_schema.rb +0 -76
@@ -0,0 +1,862 @@
1
+ # frozen_string_literal: true
2
+ require "graphql/schema/field/connection_extension"
3
+ require "graphql/schema/field/scope_extension"
4
+
5
+ module GraphQL
6
+ class Schema
7
+ class Field
8
+ include GraphQL::Schema::Member::HasArguments
9
+ include GraphQL::Schema::Member::HasAstNode
10
+ include GraphQL::Schema::Member::HasPath
11
+ include GraphQL::Schema::Member::HasValidators
12
+ extend GraphQL::Schema::FindInheritedValue
13
+ include GraphQL::Schema::FindInheritedValue::EmptyObjects
14
+ include GraphQL::Schema::Member::HasDirectives
15
+ include GraphQL::Schema::Member::HasDeprecationReason
16
+
17
+ class FieldImplementationFailed < GraphQL::Error; end
18
+
19
+ # @return [String] the GraphQL name for this field, camelized unless `camelize: false` is provided
20
+ attr_reader :name
21
+ alias :graphql_name :name
22
+
23
+ attr_writer :description
24
+
25
+ # @return [Symbol] Method or hash key on the underlying object to look up
26
+ attr_reader :method_sym
27
+
28
+ # @return [String] Method or hash key on the underlying object to look up
29
+ attr_reader :method_str
30
+
31
+ attr_reader :hash_key
32
+ attr_reader :dig_keys
33
+
34
+ # @return [Symbol] The method on the type to look up
35
+ def resolver_method
36
+ if @resolver_class
37
+ @resolver_class.resolver_method
38
+ else
39
+ @resolver_method
40
+ end
41
+ end
42
+
43
+ # @return [Class] The thing this field was defined on (type, mutation, resolver)
44
+ attr_accessor :owner
45
+
46
+ # @return [Class] The GraphQL type this field belongs to. (For fields defined on mutations, it's the payload type)
47
+ def owner_type
48
+ @owner_type ||= if owner.nil?
49
+ raise GraphQL::InvariantError, "Field #{original_name.inspect} (graphql name: #{graphql_name.inspect}) has no owner, but all fields should have an owner. How did this happen?!"
50
+ elsif owner < GraphQL::Schema::Mutation
51
+ owner.payload_type
52
+ else
53
+ owner
54
+ end
55
+ end
56
+
57
+ # @return [Symbol] the original name of the field, passed in by the user
58
+ attr_reader :original_name
59
+
60
+ # @return [Class, nil] The {Schema::Resolver} this field was derived from, if there is one
61
+ def resolver
62
+ @resolver_class
63
+ end
64
+
65
+ # @return [Boolean] Is this field a predefined introspection field?
66
+ def introspection?
67
+ @introspection
68
+ end
69
+
70
+ def inspect
71
+ "#<#{self.class} #{path}#{all_argument_definitions.any? ? "(...)" : ""}: #{type.to_type_signature}>"
72
+ end
73
+
74
+ alias :mutation :resolver
75
+
76
+ # @return [Boolean] Apply tracing to this field? (Default: skip scalars, this is the override value)
77
+ attr_reader :trace
78
+
79
+ # @return [String, nil]
80
+ def subscription_scope
81
+ @subscription_scope || (@resolver_class.respond_to?(:subscription_scope) ? @resolver_class.subscription_scope : nil)
82
+ end
83
+ attr_writer :subscription_scope
84
+
85
+ # Create a field instance from a list of arguments, keyword arguments, and a block.
86
+ #
87
+ # This method implements prioritization between the `resolver` or `mutation` defaults
88
+ # and the local overrides via other keywords.
89
+ #
90
+ # It also normalizes positional arguments into keywords for {Schema::Field#initialize}.
91
+ # @param resolver [Class] A {GraphQL::Schema::Resolver} class to use for field configuration
92
+ # @param mutation [Class] A {GraphQL::Schema::Mutation} class to use for field configuration
93
+ # @param subscription [Class] A {GraphQL::Schema::Subscription} class to use for field configuration
94
+ # @return [GraphQL::Schema:Field] an instance of `self
95
+ # @see {.initialize} for other options
96
+ def self.from_options(name = nil, type = nil, desc = nil, resolver: nil, mutation: nil, subscription: nil,**kwargs, &block)
97
+ if (resolver_class = resolver || mutation || subscription)
98
+ # Add a reference to that parent class
99
+ kwargs[:resolver_class] = resolver_class
100
+ end
101
+
102
+ if name
103
+ kwargs[:name] = name
104
+ end
105
+
106
+ if !type.nil?
107
+ if desc
108
+ if kwargs[:description]
109
+ raise ArgumentError, "Provide description as a positional argument or `description:` keyword, but not both (#{desc.inspect}, #{kwargs[:description].inspect})"
110
+ end
111
+
112
+ kwargs[:description] = desc
113
+ kwargs[:type] = type
114
+ elsif (resolver || mutation) && type.is_a?(String)
115
+ # The return type should be copied from the resolver, and the second positional argument is the description
116
+ kwargs[:description] = type
117
+ else
118
+ kwargs[:type] = type
119
+ end
120
+ if type.is_a?(Class) && type < GraphQL::Schema::Mutation
121
+ raise ArgumentError, "Use `field #{name.inspect}, mutation: Mutation, ...` to provide a mutation to this field instead"
122
+ end
123
+ end
124
+ new(**kwargs, &block)
125
+ end
126
+
127
+ # Can be set with `connection: true|false` or inferred from a type name ending in `*Connection`
128
+ # @return [Boolean] if true, this field will be wrapped with Relay connection behavior
129
+ def connection?
130
+ if @connection.nil?
131
+ # Provide default based on type name
132
+ return_type_name = if @return_type_expr
133
+ Member::BuildType.to_type_name(@return_type_expr)
134
+ elsif @resolver_class && @resolver_class.type
135
+ Member::BuildType.to_type_name(@resolver_class.type)
136
+ else
137
+ # As a last ditch, try to force loading the return type:
138
+ type.unwrap.name
139
+ end
140
+ @connection = return_type_name.end_with?("Connection")
141
+ else
142
+ @connection
143
+ end
144
+ end
145
+
146
+ # @return [Boolean] if true, the return type's `.scope_items` method will be applied to this field's return value
147
+ def scoped?
148
+ if !@scope.nil?
149
+ # The default was overridden
150
+ @scope
151
+ elsif @return_type_expr
152
+ # Detect a list return type, but don't call `type` since that may eager-load an otherwise lazy-loaded type
153
+ @return_type_expr.is_a?(Array) ||
154
+ (@return_type_expr.is_a?(String) && @return_type_expr.include?("[")) ||
155
+ connection?
156
+ elsif @resolver_class
157
+ resolver_type = @resolver_class.type_expr
158
+ resolver_type.is_a?(Array) ||
159
+ (resolver_type.is_a?(String) && resolver_type.include?("[")) ||
160
+ connection?
161
+ else
162
+ false
163
+ end
164
+ end
165
+
166
+ # This extension is applied to fields when {#connection?} is true.
167
+ #
168
+ # You can override it in your base field definition.
169
+ # @return [Class] A {FieldExtension} subclass for implementing pagination behavior.
170
+ # @example Configuring a custom extension
171
+ # class Types::BaseField < GraphQL::Schema::Field
172
+ # connection_extension(MyCustomExtension)
173
+ # end
174
+ def self.connection_extension(new_extension_class = nil)
175
+ if new_extension_class
176
+ @connection_extension = new_extension_class
177
+ else
178
+ @connection_extension ||= find_inherited_value(:connection_extension, ConnectionExtension)
179
+ end
180
+ end
181
+
182
+ # @return Boolean
183
+ attr_reader :relay_node_field
184
+ # @return Boolean
185
+ attr_reader :relay_nodes_field
186
+
187
+ # @return [Boolean] Should we warn if this field's name conflicts with a built-in method?
188
+ def method_conflict_warning?
189
+ @method_conflict_warning
190
+ end
191
+
192
+ # @param name [Symbol] The underscore-cased version of this field name (will be camelized for the GraphQL API)
193
+ # @param type [Class, GraphQL::BaseType, Array] The return type of this field
194
+ # @param owner [Class] The type that this field belongs to
195
+ # @param null [Boolean] (defaults to `true`) `true` if this field may return `null`, `false` if it is never `null`
196
+ # @param description [String] Field description
197
+ # @param deprecation_reason [String] If present, the field is marked "deprecated" with this message
198
+ # @param method [Symbol] The method to call on the underlying object to resolve this field (defaults to `name`)
199
+ # @param hash_key [String, Symbol] The hash key to lookup on the underlying object (if its a Hash) to resolve this field (defaults to `name` or `name.to_s`)
200
+ # @param dig [Array<String, Symbol>] The nested hash keys to lookup on the underlying hash to resolve this field using dig
201
+ # @param resolver_method [Symbol] The method on the type to call to resolve this field (defaults to `name`)
202
+ # @param connection [Boolean] `true` if this field should get automagic connection behavior; default is to infer by `*Connection` in the return type name
203
+ # @param connection_extension [Class] The extension to add, to implement connections. If `nil`, no extension is added.
204
+ # @param max_page_size [Integer, nil] For connections, the maximum number of items to return from this field, or `nil` to allow unlimited results.
205
+ # @param default_page_size [Integer, nil] For connections, the default number of items to return from this field, or `nil` to return unlimited results.
206
+ # @param introspection [Boolean] If true, this field will be marked as `#introspection?` and the name may begin with `__`
207
+ # @param resolver_class [Class] (Private) A {Schema::Resolver} which this field was derived from. Use `resolver:` to create a field with a resolver.
208
+ # @param arguments [{String=>GraphQL::Schema::Argument, Hash}] Arguments for this field (may be added in the block, also)
209
+ # @param camelize [Boolean] If true, the field name will be camelized when building the schema
210
+ # @param complexity [Numeric] When provided, set the complexity for this field
211
+ # @param scope [Boolean] If true, the return type's `.scope_items` method will be called on the return value
212
+ # @param subscription_scope [Symbol, String] A key in `context` which will be used to scope subscription payloads
213
+ # @param extensions [Array<Class, Hash<Class => Object>>] Named extensions to apply to this field (see also {#extension})
214
+ # @param directives [Hash{Class => Hash}] Directives to apply to this field
215
+ # @param trace [Boolean] If true, a {GraphQL::Tracing} tracer will measure this scalar field
216
+ # @param broadcastable [Boolean] Whether or not this field can be distributed in subscription broadcasts
217
+ # @param ast_node [Language::Nodes::FieldDefinition, nil] If this schema was parsed from definition, this AST node defined the field
218
+ # @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
219
+ # @param validates [Array<Hash>] Configurations for validating this field
220
+ # @fallback_value [Object] A fallback value if the method is not defined
221
+ def initialize(type: nil, name: nil, owner: nil, null: nil, description: :not_given, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, connection: nil, max_page_size: :not_given, default_page_size: :not_given, scope: nil, introspection: false, camelize: true, trace: nil, complexity: nil, ast_node: nil, extras: EMPTY_ARRAY, extensions: EMPTY_ARRAY, connection_extension: self.class.connection_extension, resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, method_conflict_warning: true, broadcastable: nil, arguments: EMPTY_HASH, directives: EMPTY_HASH, validates: EMPTY_ARRAY, fallback_value: :not_given, &definition_block)
222
+ if name.nil?
223
+ raise ArgumentError, "missing first `name` argument or keyword `name:`"
224
+ end
225
+ if !(resolver_class)
226
+ if type.nil?
227
+ raise ArgumentError, "missing second `type` argument or keyword `type:`"
228
+ end
229
+ end
230
+ @original_name = name
231
+ name_s = -name.to_s
232
+ @underscored_name = -Member::BuildType.underscore(name_s)
233
+ @name = -(camelize ? Member::BuildType.camelize(name_s) : name_s)
234
+ if description != :not_given
235
+ @description = description
236
+ end
237
+ self.deprecation_reason = deprecation_reason
238
+
239
+ if method && hash_key && dig
240
+ raise ArgumentError, "Provide `method:`, `hash_key:` _or_ `dig:`, not multiple. (called with: `method: #{method.inspect}, hash_key: #{hash_key.inspect}, dig: #{dig.inspect}`)"
241
+ end
242
+
243
+ if resolver_method
244
+ if method
245
+ raise ArgumentError, "Provide `method:` _or_ `resolver_method:`, not both. (called with: `method: #{method.inspect}, resolver_method: #{resolver_method.inspect}`)"
246
+ end
247
+
248
+ if hash_key || dig
249
+ raise ArgumentError, "Provide `hash_key:`, `dig:`, _or_ `resolver_method:`, not multiple. (called with: `hash_key: #{hash_key.inspect}, dig: #{dig.inspect}, resolver_method: #{resolver_method.inspect}`)"
250
+ end
251
+ end
252
+
253
+ method_name = method || hash_key || name_s
254
+ @dig_keys = dig
255
+ if hash_key
256
+ @hash_key = hash_key
257
+ @hash_key_str = hash_key.to_s
258
+ end
259
+
260
+ @method_str = -method_name.to_s
261
+ @method_sym = method_name.to_sym
262
+ @resolver_method = (resolver_method || name_s).to_sym
263
+ @complexity = complexity
264
+ @return_type_expr = type
265
+ @return_type_null = if !null.nil?
266
+ null
267
+ elsif resolver_class
268
+ nil
269
+ else
270
+ true
271
+ end
272
+ @connection = connection
273
+ @has_max_page_size = max_page_size != :not_given
274
+ @max_page_size = max_page_size == :not_given ? nil : max_page_size
275
+ @has_default_page_size = default_page_size != :not_given
276
+ @default_page_size = default_page_size == :not_given ? nil : default_page_size
277
+ @introspection = introspection
278
+ @extras = extras
279
+ if !broadcastable.nil?
280
+ @broadcastable = broadcastable
281
+ end
282
+ @resolver_class = resolver_class
283
+ @scope = scope
284
+ @trace = trace
285
+ @relay_node_field = relay_node_field
286
+ @relay_nodes_field = relay_nodes_field
287
+ @ast_node = ast_node
288
+ @method_conflict_warning = method_conflict_warning
289
+ @fallback_value = fallback_value
290
+
291
+ arguments.each do |name, arg|
292
+ case arg
293
+ when Hash
294
+ argument(name: name, **arg)
295
+ when GraphQL::Schema::Argument
296
+ add_argument(arg)
297
+ when Array
298
+ arg.each { |a| add_argument(a) }
299
+ else
300
+ raise ArgumentError, "Unexpected argument config (#{arg.class}): #{arg.inspect}"
301
+ end
302
+ end
303
+
304
+ @owner = owner
305
+ @subscription_scope = subscription_scope
306
+
307
+ @extensions = EMPTY_ARRAY
308
+ @call_after_define = false
309
+ # This should run before connection extension,
310
+ # but should it run after the definition block?
311
+ if scoped?
312
+ self.extension(ScopeExtension)
313
+ end
314
+
315
+ # The problem with putting this after the definition_block
316
+ # is that it would override arguments
317
+ if connection? && connection_extension
318
+ self.extension(connection_extension)
319
+ end
320
+
321
+ # Do this last so we have as much context as possible when initializing them:
322
+ if extensions.any?
323
+ self.extensions(extensions)
324
+ end
325
+
326
+ if resolver_class && resolver_class.extensions.any?
327
+ self.extensions(resolver_class.extensions)
328
+ end
329
+
330
+ if directives.any?
331
+ directives.each do |(dir_class, options)|
332
+ self.directive(dir_class, **options)
333
+ end
334
+ end
335
+
336
+ if !validates.empty?
337
+ self.validates(validates)
338
+ end
339
+
340
+ if definition_block
341
+ if definition_block.arity == 1
342
+ yield self
343
+ else
344
+ instance_eval(&definition_block)
345
+ end
346
+ end
347
+
348
+ self.extensions.each(&:after_define_apply)
349
+ @call_after_define = true
350
+ end
351
+
352
+ # If true, subscription updates with this field can be shared between viewers
353
+ # @return [Boolean, nil]
354
+ # @see GraphQL::Subscriptions::BroadcastAnalyzer
355
+ def broadcastable?
356
+ if defined?(@broadcastable)
357
+ @broadcastable
358
+ elsif @resolver_class
359
+ @resolver_class.broadcastable?
360
+ else
361
+ nil
362
+ end
363
+ end
364
+
365
+ # @param text [String]
366
+ # @return [String]
367
+ def description(text = nil)
368
+ if text
369
+ @description = text
370
+ elsif defined?(@description)
371
+ @description
372
+ elsif @resolver_class
373
+ @description || @resolver_class.description
374
+ else
375
+ nil
376
+ end
377
+ end
378
+
379
+ # Read extension instances from this field,
380
+ # or add new classes/options to be initialized on this field.
381
+ # Extensions are executed in the order they are added.
382
+ #
383
+ # @example adding an extension
384
+ # extensions([MyExtensionClass])
385
+ #
386
+ # @example adding multiple extensions
387
+ # extensions([MyExtensionClass, AnotherExtensionClass])
388
+ #
389
+ # @example adding an extension with options
390
+ # extensions([MyExtensionClass, { AnotherExtensionClass => { filter: true } }])
391
+ #
392
+ # @param extensions [Array<Class, Hash<Class => Hash>>] Add extensions to this field. For hash elements, only the first key/value is used.
393
+ # @return [Array<GraphQL::Schema::FieldExtension>] extensions to apply to this field
394
+ def extensions(new_extensions = nil)
395
+ if new_extensions
396
+ new_extensions.each do |extension_config|
397
+ if extension_config.is_a?(Hash)
398
+ extension_class, options = *extension_config.to_a[0]
399
+ self.extension(extension_class, options)
400
+ else
401
+ self.extension(extension_config)
402
+ end
403
+ end
404
+ end
405
+ @extensions
406
+ end
407
+
408
+ # Add `extension` to this field, initialized with `options` if provided.
409
+ #
410
+ # @example adding an extension
411
+ # extension(MyExtensionClass)
412
+ #
413
+ # @example adding an extension with options
414
+ # extension(MyExtensionClass, filter: true)
415
+ #
416
+ # @param extension_class [Class] subclass of {Schema::FieldExtension}
417
+ # @param options [Hash] if provided, given as `options:` when initializing `extension`.
418
+ # @return [void]
419
+ def extension(extension_class, options = nil)
420
+ extension_inst = extension_class.new(field: self, options: options)
421
+ if @extensions.frozen?
422
+ @extensions = @extensions.dup
423
+ end
424
+ if @call_after_define
425
+ extension_inst.after_define_apply
426
+ end
427
+ @extensions << extension_inst
428
+ nil
429
+ end
430
+
431
+ # Read extras (as symbols) from this field,
432
+ # or add new extras to be opted into by this field's resolver.
433
+ #
434
+ # @param new_extras [Array<Symbol>] Add extras to this field
435
+ # @return [Array<Symbol>]
436
+ def extras(new_extras = nil)
437
+ if new_extras.nil?
438
+ # Read the value
439
+ field_extras = @extras
440
+ if @resolver_class && @resolver_class.extras.any?
441
+ field_extras + @resolver_class.extras
442
+ else
443
+ field_extras
444
+ end
445
+ else
446
+ if @extras.frozen?
447
+ @extras = @extras.dup
448
+ end
449
+ # Append to the set of extras on this field
450
+ @extras.concat(new_extras)
451
+ end
452
+ end
453
+
454
+ def calculate_complexity(query:, nodes:, child_complexity:)
455
+ if respond_to?(:complexity_for)
456
+ lookahead = GraphQL::Execution::Lookahead.new(query: query, field: self, ast_nodes: nodes, owner_type: owner)
457
+ complexity_for(child_complexity: child_complexity, query: query, lookahead: lookahead)
458
+ elsif connection?
459
+ arguments = query.arguments_for(nodes.first, self)
460
+ max_possible_page_size = nil
461
+ if arguments.respond_to?(:[]) # It might have been an error
462
+ if arguments[:first]
463
+ max_possible_page_size = arguments[:first]
464
+ end
465
+
466
+ if arguments[:last] && (max_possible_page_size.nil? || arguments[:last] > max_possible_page_size)
467
+ max_possible_page_size = arguments[:last]
468
+ end
469
+ end
470
+
471
+ if max_possible_page_size.nil?
472
+ max_possible_page_size = default_page_size || query.schema.default_page_size || max_page_size || query.schema.default_max_page_size
473
+ end
474
+
475
+ if max_possible_page_size.nil?
476
+ raise GraphQL::Error, "Can't calculate complexity for #{path}, no `first:`, `last:`, `default_page_size`, `max_page_size` or `default_max_page_size`"
477
+ else
478
+ metadata_complexity = 0
479
+ lookahead = GraphQL::Execution::Lookahead.new(query: query, field: self, ast_nodes: nodes, owner_type: owner)
480
+
481
+ if (page_info_lookahead = lookahead.selection(:page_info)).selected?
482
+ metadata_complexity += 1 # pageInfo
483
+ metadata_complexity += page_info_lookahead.selections.size # subfields
484
+ end
485
+
486
+ if lookahead.selects?(:total) || lookahead.selects?(:total_count) || lookahead.selects?(:count)
487
+ metadata_complexity += 1
488
+ end
489
+
490
+ nodes_edges_complexity = 0
491
+ nodes_edges_complexity += 1 if lookahead.selects?(:edges)
492
+ nodes_edges_complexity += 1 if lookahead.selects?(:nodes)
493
+
494
+ # Possible bug: selections on `edges` and `nodes` are _both_ multiplied here. Should they be?
495
+ items_complexity = child_complexity - metadata_complexity - nodes_edges_complexity
496
+ # Add 1 for _this_ field
497
+ 1 + (max_possible_page_size * items_complexity) + metadata_complexity + nodes_edges_complexity
498
+ end
499
+ else
500
+ defined_complexity = complexity
501
+ case defined_complexity
502
+ when Proc
503
+ arguments = query.arguments_for(nodes.first, self)
504
+ if arguments.is_a?(GraphQL::ExecutionError)
505
+ return child_complexity
506
+ elsif arguments.respond_to?(:keyword_arguments)
507
+ arguments = arguments.keyword_arguments
508
+ end
509
+
510
+ defined_complexity.call(query.context, arguments, child_complexity)
511
+ when Numeric
512
+ defined_complexity + child_complexity
513
+ else
514
+ raise("Invalid complexity: #{defined_complexity.inspect} on #{path} (#{inspect})")
515
+ end
516
+ end
517
+ end
518
+
519
+ def complexity(new_complexity = nil)
520
+ case new_complexity
521
+ when Proc
522
+ if new_complexity.parameters.size != 3
523
+ fail(
524
+ "A complexity proc should always accept 3 parameters: ctx, args, child_complexity. "\
525
+ "E.g.: complexity ->(ctx, args, child_complexity) { child_complexity * args[:limit] }"
526
+ )
527
+ else
528
+ @complexity = new_complexity
529
+ end
530
+ when Numeric
531
+ @complexity = new_complexity
532
+ when nil
533
+ if @resolver_class
534
+ @complexity || @resolver_class.complexity || 1
535
+ else
536
+ @complexity || 1
537
+ end
538
+ else
539
+ raise("Invalid complexity: #{new_complexity.inspect} on #{@name}")
540
+ end
541
+ end
542
+
543
+ # @return [Boolean] True if this field's {#max_page_size} should override the schema default.
544
+ def has_max_page_size?
545
+ @has_max_page_size || (@resolver_class && @resolver_class.has_max_page_size?)
546
+ end
547
+
548
+ # @return [Integer, nil] Applied to connections if {#has_max_page_size?}
549
+ def max_page_size
550
+ @max_page_size || (@resolver_class && @resolver_class.max_page_size)
551
+ end
552
+
553
+ # @return [Boolean] True if this field's {#default_page_size} should override the schema default.
554
+ def has_default_page_size?
555
+ @has_default_page_size || (@resolver_class && @resolver_class.has_default_page_size?)
556
+ end
557
+
558
+ # @return [Integer, nil] Applied to connections if {#has_default_page_size?}
559
+ def default_page_size
560
+ @default_page_size || (@resolver_class && @resolver_class.default_page_size)
561
+ end
562
+
563
+ class MissingReturnTypeError < GraphQL::Error; end
564
+ attr_writer :type
565
+
566
+ def type
567
+ if @resolver_class
568
+ return_type = @return_type_expr || @resolver_class.type_expr
569
+ if return_type.nil?
570
+ raise MissingReturnTypeError, "Can't determine the return type for #{self.path} (it has `resolver: #{@resolver_class}`, perhaps that class is missing a `type ...` declaration, or perhaps its type causes a cyclical loading issue)"
571
+ end
572
+ nullable = @return_type_null.nil? ? @resolver_class.null : @return_type_null
573
+ Member::BuildType.parse_type(return_type, null: nullable)
574
+ else
575
+ @type ||= Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
576
+ end
577
+ rescue GraphQL::Schema::InvalidDocumentError, MissingReturnTypeError => err
578
+ # Let this propagate up
579
+ raise err
580
+ rescue StandardError => err
581
+ raise MissingReturnTypeError, "Failed to build return type for #{@owner.graphql_name}.#{name} from #{@return_type_expr.inspect}: (#{err.class}) #{err.message}", err.backtrace
582
+ end
583
+
584
+ def visible?(context)
585
+ if @resolver_class
586
+ @resolver_class.visible?(context)
587
+ else
588
+ true
589
+ end
590
+ end
591
+
592
+ def accessible?(context)
593
+ if @resolver_class
594
+ @resolver_class.accessible?(context)
595
+ else
596
+ true
597
+ end
598
+ end
599
+
600
+ def authorized?(object, args, context)
601
+ if @resolver_class
602
+ # The resolver _instance_ will check itself during `resolve()`
603
+ @resolver_class.authorized?(object, context)
604
+ else
605
+ if (arg_values = context[:current_arguments])
606
+ # ^^ that's provided by the interpreter at runtime, and includes info about whether the default value was used or not.
607
+ using_arg_values = true
608
+ arg_values = arg_values.argument_values
609
+ else
610
+ arg_values = args
611
+ using_arg_values = false
612
+ end
613
+ # Faster than `.any?`
614
+ arguments(context).each_value do |arg|
615
+ arg_key = arg.keyword
616
+ if arg_values.key?(arg_key)
617
+ arg_value = arg_values[arg_key]
618
+ if using_arg_values
619
+ if arg_value.default_used?
620
+ # pass -- no auth required for default used
621
+ next
622
+ else
623
+ application_arg_value = arg_value.value
624
+ if application_arg_value.is_a?(GraphQL::Execution::Interpreter::Arguments)
625
+ application_arg_value.keyword_arguments
626
+ end
627
+ end
628
+ else
629
+ application_arg_value = arg_value
630
+ end
631
+
632
+ if !arg.authorized?(object, application_arg_value, context)
633
+ return false
634
+ end
635
+ end
636
+ end
637
+ true
638
+ end
639
+ end
640
+
641
+ # This method is called by the interpreter for each field.
642
+ # You can extend it in your base field classes.
643
+ # @param object [GraphQL::Schema::Object] An instance of some type class, wrapping an application object
644
+ # @param args [Hash] A symbol-keyed hash of Ruby keyword arguments. (Empty if no args)
645
+ # @param ctx [GraphQL::Query::Context]
646
+ def resolve(object, args, query_ctx)
647
+ # Unwrap the GraphQL object to get the application object.
648
+ application_object = object.object
649
+ method_receiver = nil
650
+ method_to_call = nil
651
+ method_args = nil
652
+
653
+ Schema::Validator.validate!(validators, application_object, query_ctx, args)
654
+
655
+ query_ctx.schema.after_lazy(self.authorized?(application_object, args, query_ctx)) do |is_authorized|
656
+ if is_authorized
657
+ with_extensions(object, args, query_ctx) do |obj, ruby_kwargs|
658
+ method_args = ruby_kwargs
659
+ if @resolver_class
660
+ if obj.is_a?(GraphQL::Schema::Object)
661
+ obj = obj.object
662
+ end
663
+ obj = @resolver_class.new(object: obj, context: query_ctx, field: self)
664
+ end
665
+
666
+ inner_object = obj.object
667
+
668
+ if defined?(@hash_key)
669
+ hash_value = if inner_object.is_a?(Hash)
670
+ inner_object.key?(@hash_key) ? inner_object[@hash_key] : inner_object[@hash_key_str]
671
+ elsif inner_object.respond_to?(:[])
672
+ inner_object[@hash_key]
673
+ else
674
+ nil
675
+ end
676
+ if hash_value == false
677
+ hash_value
678
+ else
679
+ hash_value || (@fallback_value != :not_given ? @fallback_value : nil)
680
+ end
681
+ elsif obj.respond_to?(resolver_method)
682
+ method_to_call = resolver_method
683
+ method_receiver = obj
684
+ # Call the method with kwargs, if there are any
685
+ if ruby_kwargs.any?
686
+ obj.public_send(resolver_method, **ruby_kwargs)
687
+ else
688
+ obj.public_send(resolver_method)
689
+ end
690
+ elsif inner_object.is_a?(Hash)
691
+ if @dig_keys
692
+ inner_object.dig(*@dig_keys)
693
+ elsif inner_object.key?(@method_sym)
694
+ inner_object[@method_sym]
695
+ elsif inner_object.key?(@method_str)
696
+ inner_object[@method_str]
697
+ elsif @fallback_value != :not_given
698
+ @fallback_value
699
+ else
700
+ nil
701
+ end
702
+ elsif inner_object.respond_to?(@method_sym)
703
+ method_to_call = @method_sym
704
+ method_receiver = obj.object
705
+ if ruby_kwargs.any?
706
+ inner_object.public_send(@method_sym, **ruby_kwargs)
707
+ else
708
+ inner_object.public_send(@method_sym)
709
+ end
710
+ elsif @fallback_value != :not_given
711
+ @fallback_value
712
+ else
713
+ raise <<-ERR
714
+ Failed to implement #{@owner.graphql_name}.#{@name}, tried:
715
+
716
+ - `#{obj.class}##{resolver_method}`, which did not exist
717
+ - `#{inner_object.class}##{@method_sym}`, which did not exist
718
+ - Looking up hash key `#{@method_sym.inspect}` or `#{@method_str.inspect}` on `#{inner_object}`, but it wasn't a Hash
719
+
720
+ To implement this field, define one of the methods above (and check for typos), or supply a `fallback_value`.
721
+ ERR
722
+ end
723
+ end
724
+ else
725
+ raise GraphQL::UnauthorizedFieldError.new(object: application_object, type: object.class, context: query_ctx, field: self)
726
+ end
727
+ end
728
+ rescue GraphQL::UnauthorizedFieldError => err
729
+ err.field ||= self
730
+ begin
731
+ query_ctx.schema.unauthorized_field(err)
732
+ rescue GraphQL::ExecutionError => err
733
+ err
734
+ end
735
+ rescue GraphQL::UnauthorizedError => err
736
+ begin
737
+ query_ctx.schema.unauthorized_object(err)
738
+ rescue GraphQL::ExecutionError => err
739
+ err
740
+ end
741
+ rescue ArgumentError
742
+ if method_receiver && method_to_call
743
+ assert_satisfactory_implementation(method_receiver, method_to_call, method_args)
744
+ end
745
+ # if the line above doesn't raise, re-raise
746
+ raise
747
+ end
748
+
749
+ # @param ctx [GraphQL::Query::Context]
750
+ def fetch_extra(extra_name, ctx)
751
+ if extra_name != :path && extra_name != :ast_node && respond_to?(extra_name)
752
+ self.public_send(extra_name)
753
+ elsif ctx.respond_to?(extra_name)
754
+ ctx.public_send(extra_name)
755
+ else
756
+ raise GraphQL::RequiredImplementationMissingError, "Unknown field extra for #{self.path}: #{extra_name.inspect}"
757
+ end
758
+ end
759
+
760
+ private
761
+
762
+ def assert_satisfactory_implementation(receiver, method_name, ruby_kwargs)
763
+ method_defn = receiver.method(method_name)
764
+ unsatisfied_ruby_kwargs = ruby_kwargs.dup
765
+ unsatisfied_method_params = []
766
+ encountered_keyrest = false
767
+ method_defn.parameters.each do |(param_type, param_name)|
768
+ case param_type
769
+ when :key
770
+ unsatisfied_ruby_kwargs.delete(param_name)
771
+ when :keyreq
772
+ if unsatisfied_ruby_kwargs.key?(param_name)
773
+ unsatisfied_ruby_kwargs.delete(param_name)
774
+ else
775
+ unsatisfied_method_params << "- `#{param_name}:` is required by Ruby, but not by GraphQL. Consider `#{param_name}: nil` instead, or making this argument required in GraphQL."
776
+ end
777
+ when :keyrest
778
+ encountered_keyrest = true
779
+ when :req
780
+ unsatisfied_method_params << "- `#{param_name}` is required by Ruby, but GraphQL doesn't pass positional arguments. If it's meant to be a GraphQL argument, use `#{param_name}:` instead. Otherwise, remove it."
781
+ when :opt, :rest
782
+ # This is fine, although it will never be present
783
+ end
784
+ end
785
+
786
+ if encountered_keyrest
787
+ unsatisfied_ruby_kwargs.clear
788
+ end
789
+
790
+ if unsatisfied_ruby_kwargs.any? || unsatisfied_method_params.any?
791
+ raise FieldImplementationFailed.new, <<-ERR
792
+ Failed to call `#{method_name.inspect}` on #{receiver.inspect} because the Ruby method params were incompatible with the GraphQL arguments:
793
+
794
+ #{ unsatisfied_ruby_kwargs
795
+ .map { |key, value| "- `#{key}: #{value}` was given by GraphQL but not defined in the Ruby method. Add `#{key}:` to the method parameters." }
796
+ .concat(unsatisfied_method_params)
797
+ .join("\n") }
798
+ ERR
799
+ end
800
+ end
801
+
802
+ # Wrap execution with hooks.
803
+ # Written iteratively to avoid big stack traces.
804
+ # @return [Object] Whatever the
805
+ def with_extensions(obj, args, ctx)
806
+ if @extensions.empty?
807
+ yield(obj, args)
808
+ else
809
+ # This is a hack to get the _last_ value for extended obj and args,
810
+ # in case one of the extensions doesn't `yield`.
811
+ # (There's another implementation that uses multiple-return, but I'm wary of the perf cost of the extra arrays)
812
+ extended = { args: args, obj: obj, memos: nil, added_extras: nil }
813
+ value = run_extensions_before_resolve(obj, args, ctx, extended) do |obj, args|
814
+ if (added_extras = extended[:added_extras])
815
+ args = args.dup
816
+ added_extras.each { |e| args.delete(e) }
817
+ end
818
+ yield(obj, args)
819
+ end
820
+
821
+ extended_obj = extended[:obj]
822
+ extended_args = extended[:args]
823
+ memos = extended[:memos] || EMPTY_HASH
824
+
825
+ ctx.schema.after_lazy(value) do |resolved_value|
826
+ idx = 0
827
+ @extensions.each do |ext|
828
+ memo = memos[idx]
829
+ # TODO after_lazy?
830
+ resolved_value = ext.after_resolve(object: extended_obj, arguments: extended_args, context: ctx, value: resolved_value, memo: memo)
831
+ idx += 1
832
+ end
833
+ resolved_value
834
+ end
835
+ end
836
+ end
837
+
838
+ def run_extensions_before_resolve(obj, args, ctx, extended, idx: 0)
839
+ extension = @extensions[idx]
840
+ if extension
841
+ extension.resolve(object: obj, arguments: args, context: ctx) do |extended_obj, extended_args, memo|
842
+ if memo
843
+ memos = extended[:memos] ||= {}
844
+ memos[idx] = memo
845
+ end
846
+
847
+ if (extras = extension.added_extras)
848
+ ae = extended[:added_extras] ||= []
849
+ ae.concat(extras)
850
+ end
851
+
852
+ extended[:obj] = extended_obj
853
+ extended[:args] = extended_args
854
+ run_extensions_before_resolve(extended_obj, extended_args, ctx, extended, idx: idx + 1) { |o, a| yield(o, a) }
855
+ end
856
+ else
857
+ yield(obj, args)
858
+ end
859
+ end
860
+ end
861
+ end
862
+ end