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,179 @@
1
+ # frozen_string_literal: true
2
+ require "graphql/types/string"
3
+
4
+ module GraphQL
5
+ class Schema
6
+ # Mutations that extend this base class get some conventions added for free:
7
+ #
8
+ # - An argument called `clientMutationId` is _always_ added, but it's not passed
9
+ # to the resolve method. The value is re-inserted to the response. (It's for
10
+ # client libraries to manage optimistic updates.)
11
+ # - The returned object type always has a field called `clientMutationId` to support that.
12
+ # - The mutation accepts one argument called `input`, `argument`s defined in the mutation
13
+ # class are added to that input object, which is generated by the mutation.
14
+ #
15
+ # These conventions were first specified by Relay Classic, but they come in handy:
16
+ #
17
+ # - `clientMutationId` supports optimistic updates and cache rollbacks on the client
18
+ # - using a single `input:` argument makes it easy to post whole JSON objects to the mutation
19
+ # using one GraphQL variable (`$input`) instead of making a separate variable for each argument.
20
+ #
21
+ # @see {GraphQL::Schema::Mutation} for an example, it's basically the same.
22
+ #
23
+ class RelayClassicMutation < GraphQL::Schema::Mutation
24
+ # The payload should always include this field
25
+ field(:client_mutation_id, String, "A unique identifier for the client performing the mutation.")
26
+ # Relay classic default:
27
+ null(true)
28
+
29
+ # Override {GraphQL::Schema::Resolver#resolve_with_support} to
30
+ # delete `client_mutation_id` from the kwargs.
31
+ def resolve_with_support(**inputs)
32
+ input = inputs[:input].to_kwargs
33
+
34
+ new_extras = field ? field.extras : []
35
+ all_extras = self.class.extras + new_extras
36
+
37
+ # Transfer these from the top-level hash to the
38
+ # shortcutted `input:` object
39
+ all_extras.each do |ext|
40
+ # It's possible that the `extra` was not passed along by this point,
41
+ # don't re-add it if it wasn't given here.
42
+ if inputs.key?(ext)
43
+ input[ext] = inputs[ext]
44
+ end
45
+ end
46
+
47
+ if input
48
+ # This is handled by Relay::Mutation::Resolve, a bit hacky, but here we are.
49
+ input_kwargs = input.to_h
50
+ client_mutation_id = input_kwargs.delete(:client_mutation_id)
51
+ else
52
+ # Relay Classic Mutations with no `argument`s
53
+ # don't require `input:`
54
+ input_kwargs = {}
55
+ end
56
+
57
+ return_value = if input_kwargs.any?
58
+ super(**input_kwargs)
59
+ else
60
+ super()
61
+ end
62
+
63
+ context.schema.after_lazy(return_value) do |return_hash|
64
+ # It might be an error
65
+ if return_hash.is_a?(Hash)
66
+ return_hash[:client_mutation_id] = client_mutation_id
67
+ end
68
+ return_hash
69
+ end
70
+ end
71
+
72
+ class << self
73
+ def dummy
74
+ @dummy ||= begin
75
+ d = Class.new(GraphQL::Schema::Resolver)
76
+ d.argument_class(self.argument_class)
77
+ # TODO make this lazier?
78
+ d.argument(:input, input_type, description: "Parameters for #{self.graphql_name}")
79
+ d
80
+ end
81
+ end
82
+
83
+ def field_arguments(context = GraphQL::Query::NullContext)
84
+ dummy.arguments(context)
85
+ end
86
+
87
+ def get_field_argument(name, context = GraphQL::Query::NullContext)
88
+ dummy.get_argument(name, context)
89
+ end
90
+
91
+ def own_field_arguments
92
+ dummy.own_arguments
93
+ end
94
+
95
+ def all_field_argument_definitions
96
+ dummy.all_argument_definitions
97
+ end
98
+
99
+ # Also apply this argument to the input type:
100
+ def argument(*args, own_argument: false, **kwargs, &block)
101
+ it = input_type # make sure any inherited arguments are already added to it
102
+ arg = super(*args, **kwargs, &block)
103
+
104
+ # This definition might be overriding something inherited;
105
+ # if it is, remove the inherited definition so it's not confused at runtime as having multiple definitions
106
+ prev_args = it.own_arguments[arg.graphql_name]
107
+ case prev_args
108
+ when GraphQL::Schema::Argument
109
+ if prev_args.owner != self
110
+ it.own_arguments.delete(arg.graphql_name)
111
+ end
112
+ when Array
113
+ prev_args.reject! { |a| a.owner != self }
114
+ if prev_args.empty?
115
+ it.own_arguments.delete(arg.graphql_name)
116
+ end
117
+ end
118
+
119
+ it.add_argument(arg)
120
+ arg
121
+ end
122
+
123
+ # The base class for generated input object types
124
+ # @param new_class [Class] The base class to use for generating input object definitions
125
+ # @return [Class] The base class for this mutation's generated input object (default is {GraphQL::Schema::InputObject})
126
+ def input_object_class(new_class = nil)
127
+ if new_class
128
+ @input_object_class = new_class
129
+ end
130
+ @input_object_class || (superclass.respond_to?(:input_object_class) ? superclass.input_object_class : GraphQL::Schema::InputObject)
131
+ end
132
+
133
+ # @param new_input_type [Class, nil] If provided, it configures this mutation to accept `new_input_type` instead of generating an input type
134
+ # @return [Class] The generated {Schema::InputObject} class for this mutation's `input`
135
+ def input_type(new_input_type = nil)
136
+ if new_input_type
137
+ @input_type = new_input_type
138
+ end
139
+ @input_type ||= generate_input_type
140
+ end
141
+
142
+ private
143
+
144
+ # Generate the input type for the `input:` argument
145
+ # To customize how input objects are generated, override this method
146
+ # @return [Class] a subclass of {.input_object_class}
147
+ def generate_input_type
148
+ mutation_args = all_argument_definitions
149
+ mutation_class = self
150
+ Class.new(input_object_class) do
151
+ class << self
152
+ def default_graphql_name
153
+ "#{self.mutation.graphql_name}Input"
154
+ end
155
+
156
+ def description(new_desc = nil)
157
+ super || "Autogenerated input type of #{self.mutation.graphql_name}"
158
+ end
159
+ end
160
+ mutation(mutation_class)
161
+ # these might be inherited:
162
+ mutation_args.each do |arg|
163
+ add_argument(arg)
164
+ end
165
+ argument :client_mutation_id, String, "A unique identifier for the client performing the mutation.", required: false
166
+ end
167
+ end
168
+ end
169
+
170
+ private
171
+
172
+ def authorize_arguments(args, values)
173
+ # remove the `input` wrapper to match values
174
+ input_args = args["input"].type.unwrap.arguments(context)
175
+ super(input_args, values)
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Resolver
6
+ # Adds `field(...)` helper to resolvers so that they can
7
+ # generate payload types.
8
+ #
9
+ # Or, an already-defined one can be attached with `payload_type(...)`.
10
+ module HasPayloadType
11
+ # Call this method to get the derived return type of the mutation,
12
+ # or use it as a configuration method to assign a return type
13
+ # instead of generating one.
14
+ # @param new_payload_type [Class, nil] If a type definition class is provided, it will be used as the return type of the mutation field
15
+ # @return [Class] The object type which this mutation returns.
16
+ def payload_type(new_payload_type = nil)
17
+ if new_payload_type
18
+ @payload_type = new_payload_type
19
+ end
20
+ @payload_type ||= generate_payload_type
21
+ end
22
+
23
+ def type(new_type = nil, null: nil)
24
+ if new_type
25
+ payload_type(new_type)
26
+ if !null.nil?
27
+ self.null(null)
28
+ end
29
+ else
30
+ super()
31
+ end
32
+ end
33
+
34
+ alias :type_expr :payload_type
35
+
36
+ def field_class(new_class = nil)
37
+ if new_class
38
+ @field_class = new_class
39
+ elsif defined?(@field_class) && @field_class
40
+ @field_class
41
+ else
42
+ find_inherited_value(:field_class, GraphQL::Schema::Field)
43
+ end
44
+ end
45
+
46
+ # An object class to use for deriving return types
47
+ # @param new_class [Class, nil] Defaults to {GraphQL::Schema::Object}
48
+ # @return [Class]
49
+ def object_class(new_class = nil)
50
+ if new_class
51
+ if defined?(@payload_type)
52
+ raise "Can't configure `object_class(...)` after the payload type has already been initialized. Move this configuration higher up the class definition."
53
+ end
54
+ @object_class = new_class
55
+ else
56
+ @object_class || find_inherited_value(:object_class, GraphQL::Schema::Object)
57
+ end
58
+ end
59
+
60
+ NO_INTERFACES = [].freeze
61
+
62
+ def field(*args, **kwargs, &block)
63
+ pt = payload_type # make sure it's initialized with any inherited fields
64
+ field_defn = super
65
+
66
+ # Remove any inherited fields to avoid false conflicts at runtime
67
+ prev_fields = pt.own_fields[field_defn.graphql_name]
68
+ case prev_fields
69
+ when GraphQL::Schema::Field
70
+ if prev_fields.owner != self
71
+ pt.own_fields.delete(field_defn.graphql_name)
72
+ end
73
+ when Array
74
+ prev_fields.reject! { |f| f.owner != self }
75
+ if prev_fields.empty?
76
+ pt.own_fields.delete(field_defn.graphql_name)
77
+ end
78
+ end
79
+
80
+ pt.add_field(field_defn, method_conflict_warning: false)
81
+ field_defn
82
+ end
83
+
84
+ private
85
+
86
+ # Build a subclass of {.object_class} based on `self`.
87
+ # This value will be cached as `{.payload_type}`.
88
+ # Override this hook to customize return type generation.
89
+ def generate_payload_type
90
+ resolver_name = graphql_name
91
+ resolver_fields = all_field_definitions
92
+ Class.new(object_class) do
93
+ graphql_name("#{resolver_name}Payload")
94
+ description("Autogenerated return type of #{resolver_name}.")
95
+ resolver_fields.each do |f|
96
+ # Reattach the already-defined field here
97
+ # (The field's `.owner` will still point to the mutation, not the object type, I think)
98
+ # Don't re-warn about a method conflict. Since this type is generated, it should be fixed in the resolver instead.
99
+ add_field(f, method_conflict_warning: false)
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,402 @@
1
+ # frozen_string_literal: true
2
+ require "graphql/schema/resolver/has_payload_type"
3
+
4
+ module GraphQL
5
+ class Schema
6
+ # A class-based container for field configuration and resolution logic. It supports:
7
+ #
8
+ # - Arguments, via `.argument(...)` helper, which will be applied to the field.
9
+ # - Return type, via `.type(..., null: ...)`, which will be applied to the field.
10
+ # - Description, via `.description(...)`, which will be applied to the field
11
+ # - Resolution, via `#resolve(**args)` method, which will be called to resolve the field.
12
+ # - `#object` and `#context` accessors for use during `#resolve`.
13
+ #
14
+ # Resolvers can be attached with the `resolver:` option in a `field(...)` call.
15
+ #
16
+ # A resolver's configuration may be overridden with other keywords in the `field(...)` call.
17
+ #
18
+ # @see {GraphQL::Schema::Mutation} for a concrete subclass of `Resolver`.
19
+ # @see {GraphQL::Function} `Resolver` is a replacement for `GraphQL::Function`
20
+ class Resolver
21
+ include Schema::Member::GraphQLTypeNames
22
+ # Really we only need description from here, but:
23
+ extend Schema::Member::BaseDSLMethods
24
+ extend GraphQL::Schema::Member::HasArguments
25
+ extend GraphQL::Schema::Member::HasValidators
26
+ include Schema::Member::HasPath
27
+ extend Schema::Member::HasPath
28
+
29
+ # @param object [Object] The application object that this field is being resolved on
30
+ # @param context [GraphQL::Query::Context]
31
+ # @param field [GraphQL::Schema::Field]
32
+ def initialize(object:, context:, field:)
33
+ @object = object
34
+ @context = context
35
+ @field = field
36
+ # Since this hash is constantly rebuilt, cache it for this call
37
+ @arguments_by_keyword = {}
38
+ self.class.arguments(context).each do |name, arg|
39
+ @arguments_by_keyword[arg.keyword] = arg
40
+ end
41
+ @prepared_arguments = nil
42
+ end
43
+
44
+ # @return [Object] The application object this field is being resolved on
45
+ attr_reader :object
46
+
47
+ # @return [GraphQL::Query::Context]
48
+ attr_reader :context
49
+
50
+ # @return [GraphQL::Dataloader]
51
+ def dataloader
52
+ context.dataloader
53
+ end
54
+
55
+ # @return [GraphQL::Schema::Field]
56
+ attr_reader :field
57
+
58
+ def arguments
59
+ @prepared_arguments || raise("Arguments have not been prepared yet, still waiting for #load_arguments to resolve. (Call `.arguments` later in the code.)")
60
+ end
61
+
62
+ # This method is _actually_ called by the runtime,
63
+ # it does some preparation and then eventually calls
64
+ # the user-defined `#resolve` method.
65
+ # @api private
66
+ def resolve_with_support(**args)
67
+ # First call the ready? hook which may raise
68
+ ready_val = if args.any?
69
+ ready?(**args)
70
+ else
71
+ ready?
72
+ end
73
+ context.schema.after_lazy(ready_val) do |is_ready, ready_early_return|
74
+ if ready_early_return
75
+ if is_ready != false
76
+ raise "Unexpected result from #ready? (expected `true`, `false` or `[false, {...}]`): [#{is_ready.inspect}, #{ready_early_return.inspect}]"
77
+ else
78
+ ready_early_return
79
+ end
80
+ elsif is_ready
81
+ # Then call each prepare hook, which may return a different value
82
+ # for that argument, or may return a lazy object
83
+ load_arguments_val = load_arguments(args)
84
+ context.schema.after_lazy(load_arguments_val) do |loaded_args|
85
+ @prepared_arguments = loaded_args
86
+ Schema::Validator.validate!(self.class.validators, object, context, loaded_args, as: @field)
87
+ # Then call `authorized?`, which may raise or may return a lazy object
88
+ authorized_val = if loaded_args.any?
89
+ authorized?(**loaded_args)
90
+ else
91
+ authorized?
92
+ end
93
+ context.schema.after_lazy(authorized_val) do |(authorized_result, early_return)|
94
+ # If the `authorized?` returned two values, `false, early_return`,
95
+ # then use the early return value instead of continuing
96
+ if early_return
97
+ if authorized_result == false
98
+ early_return
99
+ else
100
+ raise "Unexpected result from #authorized? (expected `true`, `false` or `[false, {...}]`): [#{authorized_result.inspect}, #{early_return.inspect}]"
101
+ end
102
+ elsif authorized_result
103
+ # Finally, all the hooks have passed, so resolve it
104
+ if loaded_args.any?
105
+ public_send(self.class.resolve_method, **loaded_args)
106
+ else
107
+ public_send(self.class.resolve_method)
108
+ end
109
+ else
110
+ raise GraphQL::UnauthorizedFieldError.new(context: context, object: object, type: field.owner, field: field)
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ # Do the work. Everything happens here.
119
+ # @return [Object] An object corresponding to the return type
120
+ def resolve(**args)
121
+ raise GraphQL::RequiredImplementationMissingError, "#{self.class.name}#resolve should execute the field's logic"
122
+ end
123
+
124
+ # Called before arguments are prepared.
125
+ # Implement this hook to make checks before doing any work.
126
+ #
127
+ # If it returns a lazy object (like a promise), it will be synced by GraphQL
128
+ # (but the resulting value won't be used).
129
+ #
130
+ # @param args [Hash] The input arguments, if there are any
131
+ # @raise [GraphQL::ExecutionError] To add an error to the response
132
+ # @raise [GraphQL::UnauthorizedError] To signal an authorization failure
133
+ # @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
134
+ def ready?(**args)
135
+ true
136
+ end
137
+
138
+ # Called after arguments are loaded, but before resolving.
139
+ #
140
+ # Override it to check everything before calling the mutation.
141
+ # @param inputs [Hash] The input arguments
142
+ # @raise [GraphQL::ExecutionError] To add an error to the response
143
+ # @raise [GraphQL::UnauthorizedError] To signal an authorization failure
144
+ # @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
145
+ def authorized?(**inputs)
146
+ arg_owner = @field # || self.class
147
+ args = arg_owner.arguments(context)
148
+ authorize_arguments(args, inputs)
149
+ end
150
+
151
+ # Called when an object loaded by `loads:` fails the `.authorized?` check for its resolved GraphQL object type.
152
+ #
153
+ # By default, the error is re-raised and passed along to {{Schema.unauthorized_object}}.
154
+ #
155
+ # Any value returned here will be used _instead of_ of the loaded object.
156
+ # @param err [GraphQL::UnauthorizedError]
157
+ def unauthorized_object(err)
158
+ raise err
159
+ end
160
+
161
+ private
162
+
163
+ def authorize_arguments(args, inputs)
164
+ args.each_value do |argument|
165
+ arg_keyword = argument.keyword
166
+ if inputs.key?(arg_keyword) && !(arg_value = inputs[arg_keyword]).nil? && (arg_value != argument.default_value)
167
+ arg_auth, err = argument.authorized?(self, arg_value, context)
168
+ if !arg_auth
169
+ return arg_auth, err
170
+ else
171
+ true
172
+ end
173
+ else
174
+ true
175
+ end
176
+ end
177
+ end
178
+
179
+ def load_arguments(args)
180
+ prepared_args = {}
181
+ prepare_lazies = []
182
+
183
+ args.each do |key, value|
184
+ arg_defn = @arguments_by_keyword[key]
185
+ if arg_defn
186
+ prepped_value = prepared_args[key] = arg_defn.load_and_authorize_value(self, value, context)
187
+ if context.schema.lazy?(prepped_value)
188
+ prepare_lazies << context.schema.after_lazy(prepped_value) do |finished_prepped_value|
189
+ prepared_args[key] = finished_prepped_value
190
+ end
191
+ end
192
+ else
193
+ # these are `extras:`
194
+ prepared_args[key] = value
195
+ end
196
+ end
197
+
198
+ # Avoid returning a lazy if none are needed
199
+ if prepare_lazies.any?
200
+ GraphQL::Execution::Lazy.all(prepare_lazies).then { prepared_args }
201
+ else
202
+ prepared_args
203
+ end
204
+ end
205
+
206
+ def get_argument(name, context = GraphQL::Query::NullContext)
207
+ self.class.get_argument(name, context)
208
+ end
209
+
210
+ class << self
211
+ def field_arguments(context = GraphQL::Query::NullContext)
212
+ arguments(context)
213
+ end
214
+
215
+ def get_field_argument(name, context = GraphQL::Query::NullContext)
216
+ get_argument(name, context)
217
+ end
218
+
219
+ def all_field_argument_definitions
220
+ all_argument_definitions
221
+ end
222
+
223
+ # Default `:resolve` set below.
224
+ # @return [Symbol] The method to call on instances of this object to resolve the field
225
+ def resolve_method(new_method = nil)
226
+ if new_method
227
+ @resolve_method = new_method
228
+ end
229
+ @resolve_method || (superclass.respond_to?(:resolve_method) ? superclass.resolve_method : :resolve)
230
+ end
231
+
232
+ # Additional info injected into {#resolve}
233
+ # @see {GraphQL::Schema::Field#extras}
234
+ def extras(new_extras = nil)
235
+ if new_extras
236
+ @own_extras = new_extras
237
+ end
238
+ own_extras = @own_extras || []
239
+ own_extras + (superclass.respond_to?(:extras) ? superclass.extras : [])
240
+ end
241
+
242
+ # If `true` (default), then the return type for this resolver will be nullable.
243
+ # If `false`, then the return type is non-null.
244
+ #
245
+ # @see #type which sets the return type of this field and accepts a `null:` option
246
+ # @param allow_null [Boolean] Whether or not the response can be null
247
+ def null(allow_null = nil)
248
+ if !allow_null.nil?
249
+ @null = allow_null
250
+ end
251
+
252
+ @null.nil? ? (superclass.respond_to?(:null) ? superclass.null : true) : @null
253
+ end
254
+
255
+ def resolver_method(new_method_name = nil)
256
+ if new_method_name
257
+ @resolver_method = new_method_name
258
+ else
259
+ @resolver_method || :resolve_with_support
260
+ end
261
+ end
262
+
263
+ # Call this method to get the return type of the field,
264
+ # or use it as a configuration method to assign a return type
265
+ # instead of generating one.
266
+ # TODO unify with {#null}
267
+ # @param new_type [Class, Array<Class>, nil] If a type definition class is provided, it will be used as the return type of the field
268
+ # @param null [true, false] Whether or not the field may return `nil`
269
+ # @return [Class] The type which this field returns.
270
+ def type(new_type = nil, null: nil)
271
+ if new_type
272
+ if null.nil?
273
+ raise ArgumentError, "required argument `null:` is missing"
274
+ end
275
+ @type_expr = new_type
276
+ @null = null
277
+ else
278
+ if type_expr
279
+ GraphQL::Schema::Member::BuildType.parse_type(type_expr, null: self.null)
280
+ elsif superclass.respond_to?(:type)
281
+ superclass.type
282
+ else
283
+ nil
284
+ end
285
+ end
286
+ end
287
+
288
+ # Specifies the complexity of the field. Defaults to `1`
289
+ # @return [Integer, Proc]
290
+ def complexity(new_complexity = nil)
291
+ if new_complexity
292
+ @complexity = new_complexity
293
+ end
294
+ @complexity || (superclass.respond_to?(:complexity) ? superclass.complexity : 1)
295
+ end
296
+
297
+ def broadcastable(new_broadcastable)
298
+ @broadcastable = new_broadcastable
299
+ end
300
+
301
+ # @return [Boolean, nil]
302
+ def broadcastable?
303
+ if defined?(@broadcastable)
304
+ @broadcastable
305
+ else
306
+ (superclass.respond_to?(:broadcastable?) ? superclass.broadcastable? : nil)
307
+ end
308
+ end
309
+
310
+ # Get or set the `max_page_size:` which will be configured for fields using this resolver
311
+ # (`nil` means "unlimited max page size".)
312
+ # @param max_page_size [Integer, nil] Set a new value
313
+ # @return [Integer, nil] The `max_page_size` assigned to fields that use this resolver
314
+ def max_page_size(new_max_page_size = :not_given)
315
+ if new_max_page_size != :not_given
316
+ @max_page_size = new_max_page_size
317
+ elsif defined?(@max_page_size)
318
+ @max_page_size
319
+ elsif superclass.respond_to?(:max_page_size)
320
+ superclass.max_page_size
321
+ else
322
+ nil
323
+ end
324
+ end
325
+
326
+ # @return [Boolean] `true` if this resolver or a superclass has an assigned `max_page_size`
327
+ def has_max_page_size?
328
+ (!!defined?(@max_page_size)) || (superclass.respond_to?(:has_max_page_size?) && superclass.has_max_page_size?)
329
+ end
330
+
331
+ # Get or set the `default_page_size:` which will be configured for fields using this resolver
332
+ # (`nil` means "unlimited default page size".)
333
+ # @param default_page_size [Integer, nil] Set a new value
334
+ # @return [Integer, nil] The `default_page_size` assigned to fields that use this resolver
335
+ def default_page_size(new_default_page_size = :not_given)
336
+ if new_default_page_size != :not_given
337
+ @default_page_size = new_default_page_size
338
+ elsif defined?(@default_page_size)
339
+ @default_page_size
340
+ elsif superclass.respond_to?(:default_page_size)
341
+ superclass.default_page_size
342
+ else
343
+ nil
344
+ end
345
+ end
346
+
347
+ # @return [Boolean] `true` if this resolver or a superclass has an assigned `default_page_size`
348
+ def has_default_page_size?
349
+ (!!defined?(@default_page_size)) || (superclass.respond_to?(:has_default_page_size?) && superclass.has_default_page_size?)
350
+ end
351
+
352
+ # A non-normalized type configuration, without `null` applied
353
+ def type_expr
354
+ @type_expr || (superclass.respond_to?(:type_expr) ? superclass.type_expr : nil)
355
+ end
356
+
357
+ # Add an argument to this field's signature, but
358
+ # also add some preparation hook methods which will be used for this argument
359
+ # @see {GraphQL::Schema::Argument#initialize} for the signature
360
+ def argument(*args, **kwargs, &block)
361
+ # Use `from_resolver: true` to short-circuit the InputObject's own `loads:` implementation
362
+ # so that we can support `#load_{x}` methods below.
363
+ super(*args, from_resolver: true, **kwargs)
364
+ end
365
+
366
+ # Registers new extension
367
+ # @param extension [Class] Extension class
368
+ # @param options [Hash] Optional extension options
369
+ def extension(extension, **options)
370
+ @own_extensions ||= []
371
+ @own_extensions << {extension => options}
372
+ end
373
+
374
+ # @api private
375
+ def extensions
376
+ own_exts = @own_extensions
377
+ # Jump through some hoops to avoid creating arrays when we don't actually need them
378
+ if superclass.respond_to?(:extensions)
379
+ s_exts = superclass.extensions
380
+ if own_exts
381
+ if s_exts.any?
382
+ own_exts + s_exts
383
+ else
384
+ own_exts
385
+ end
386
+ else
387
+ s_exts
388
+ end
389
+ else
390
+ own_exts || EMPTY_ARRAY
391
+ end
392
+ end
393
+
394
+ private
395
+
396
+ def own_extensions
397
+ @own_extensions
398
+ end
399
+ end
400
+ end
401
+ end
402
+ end