graphql 1.9.17 → 2.0.20

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 (413) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +21 -10
  3. data/lib/generators/graphql/enum_generator.rb +4 -10
  4. data/lib/generators/graphql/field_extractor.rb +31 -0
  5. data/lib/generators/graphql/input_generator.rb +50 -0
  6. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  7. data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +2 -0
  8. data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +2 -0
  9. data/lib/generators/graphql/install_generator.rb +45 -8
  10. data/lib/generators/graphql/interface_generator.rb +7 -7
  11. data/lib/generators/graphql/loader_generator.rb +1 -0
  12. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  13. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  14. data/lib/generators/graphql/mutation_generator.rb +6 -30
  15. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  16. data/lib/generators/graphql/object_generator.rb +28 -12
  17. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  18. data/lib/generators/graphql/relay.rb +49 -0
  19. data/lib/generators/graphql/relay_generator.rb +21 -0
  20. data/lib/generators/graphql/scalar_generator.rb +4 -2
  21. data/lib/generators/graphql/templates/base_argument.erb +2 -0
  22. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  23. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  24. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  25. data/lib/generators/graphql/templates/base_field.erb +2 -0
  26. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  27. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  28. data/lib/generators/graphql/templates/base_object.erb +2 -0
  29. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  30. data/lib/generators/graphql/templates/base_union.erb +2 -0
  31. data/lib/generators/graphql/templates/enum.erb +7 -1
  32. data/lib/generators/graphql/templates/graphql_controller.erb +16 -12
  33. data/lib/generators/graphql/templates/input.erb +9 -0
  34. data/lib/generators/graphql/templates/interface.erb +6 -2
  35. data/lib/generators/graphql/templates/loader.erb +2 -0
  36. data/lib/generators/graphql/templates/mutation.erb +3 -1
  37. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  38. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  39. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  40. data/lib/generators/graphql/templates/node_type.erb +9 -0
  41. data/lib/generators/graphql/templates/object.erb +7 -3
  42. data/lib/generators/graphql/templates/query_type.erb +3 -3
  43. data/lib/generators/graphql/templates/scalar.erb +5 -1
  44. data/lib/generators/graphql/templates/schema.erb +25 -27
  45. data/lib/generators/graphql/templates/union.erb +6 -2
  46. data/lib/generators/graphql/type_generator.rb +47 -10
  47. data/lib/generators/graphql/union_generator.rb +5 -5
  48. data/lib/graphql/analysis/ast/field_usage.rb +31 -2
  49. data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
  50. data/lib/graphql/analysis/ast/query_complexity.rb +175 -68
  51. data/lib/graphql/analysis/ast/query_depth.rb +0 -1
  52. data/lib/graphql/analysis/ast/visitor.rb +54 -38
  53. data/lib/graphql/analysis/ast.rb +16 -16
  54. data/lib/graphql/analysis.rb +0 -7
  55. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  56. data/lib/graphql/backtrace/table.rb +37 -16
  57. data/lib/graphql/backtrace/traced_error.rb +0 -1
  58. data/lib/graphql/backtrace/tracer.rb +39 -9
  59. data/lib/graphql/backtrace.rb +20 -17
  60. data/lib/graphql/dataloader/null_dataloader.rb +24 -0
  61. data/lib/graphql/dataloader/request.rb +19 -0
  62. data/lib/graphql/dataloader/request_all.rb +19 -0
  63. data/lib/graphql/dataloader/source.rb +164 -0
  64. data/lib/graphql/dataloader.rb +311 -0
  65. data/lib/graphql/date_encoding_error.rb +16 -0
  66. data/lib/graphql/deprecation.rb +9 -0
  67. data/lib/graphql/dig.rb +1 -1
  68. data/lib/graphql/execution/directive_checks.rb +2 -2
  69. data/lib/graphql/execution/errors.rb +77 -45
  70. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  71. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  72. data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
  73. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  74. data/lib/graphql/execution/interpreter/resolve.rb +62 -24
  75. data/lib/graphql/execution/interpreter/runtime.rb +773 -399
  76. data/lib/graphql/execution/interpreter.rb +206 -74
  77. data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
  78. data/lib/graphql/execution/lazy.rb +11 -21
  79. data/lib/graphql/execution/lookahead.rb +65 -136
  80. data/lib/graphql/execution/multiplex.rb +6 -152
  81. data/lib/graphql/execution.rb +11 -4
  82. data/lib/graphql/filter.rb +1 -1
  83. data/lib/graphql/integer_decoding_error.rb +17 -0
  84. data/lib/graphql/integer_encoding_error.rb +18 -2
  85. data/lib/graphql/introspection/base_object.rb +2 -5
  86. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  87. data/lib/graphql/introspection/directive_type.rb +12 -6
  88. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  89. data/lib/graphql/introspection/entry_points.rb +5 -18
  90. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  91. data/lib/graphql/introspection/field_type.rb +9 -5
  92. data/lib/graphql/introspection/input_value_type.rb +41 -11
  93. data/lib/graphql/introspection/introspection_query.rb +6 -92
  94. data/lib/graphql/introspection/schema_type.rb +12 -12
  95. data/lib/graphql/introspection/type_type.rb +34 -17
  96. data/lib/graphql/introspection.rb +100 -0
  97. data/lib/graphql/invalid_null_error.rb +18 -0
  98. data/lib/graphql/language/block_string.rb +20 -5
  99. data/lib/graphql/language/cache.rb +37 -0
  100. data/lib/graphql/language/definition_slice.rb +21 -10
  101. data/lib/graphql/language/document_from_schema_definition.rb +113 -71
  102. data/lib/graphql/language/lexer.rb +216 -1462
  103. data/lib/graphql/language/nodes.rb +128 -131
  104. data/lib/graphql/language/parser.rb +957 -912
  105. data/lib/graphql/language/parser.y +148 -120
  106. data/lib/graphql/language/printer.rb +48 -23
  107. data/lib/graphql/language/sanitized_printer.rb +222 -0
  108. data/lib/graphql/language/token.rb +0 -4
  109. data/lib/graphql/language/visitor.rb +192 -84
  110. data/lib/graphql/language.rb +3 -1
  111. data/lib/graphql/name_validator.rb +2 -7
  112. data/lib/graphql/pagination/active_record_relation_connection.rb +77 -0
  113. data/lib/graphql/pagination/array_connection.rb +79 -0
  114. data/lib/graphql/pagination/connection.rb +253 -0
  115. data/lib/graphql/pagination/connections.rb +135 -0
  116. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  117. data/lib/graphql/pagination/relation_connection.rb +228 -0
  118. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  119. data/lib/graphql/pagination.rb +6 -0
  120. data/lib/graphql/parse_error.rb +0 -1
  121. data/lib/graphql/query/context.rb +204 -203
  122. data/lib/graphql/query/fingerprint.rb +26 -0
  123. data/lib/graphql/query/input_validation_result.rb +33 -7
  124. data/lib/graphql/query/null_context.rb +21 -8
  125. data/lib/graphql/query/validation_pipeline.rb +16 -38
  126. data/lib/graphql/query/variable_validation_error.rb +3 -3
  127. data/lib/graphql/query/variables.rb +39 -12
  128. data/lib/graphql/query.rb +88 -40
  129. data/lib/graphql/railtie.rb +6 -102
  130. data/lib/graphql/rake_task/validate.rb +4 -1
  131. data/lib/graphql/rake_task.rb +41 -10
  132. data/lib/graphql/relay/range_add.rb +17 -10
  133. data/lib/graphql/relay.rb +0 -15
  134. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  135. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  136. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  137. data/lib/graphql/rubocop.rb +4 -0
  138. data/lib/graphql/schema/addition.rb +245 -0
  139. data/lib/graphql/schema/argument.rb +284 -33
  140. data/lib/graphql/schema/base_64_encoder.rb +2 -0
  141. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
  142. data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
  143. data/lib/graphql/schema/build_from_definition.rb +336 -205
  144. data/lib/graphql/schema/built_in_types.rb +5 -5
  145. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  146. data/lib/graphql/schema/directive/feature.rb +1 -1
  147. data/lib/graphql/schema/directive/flagged.rb +57 -0
  148. data/lib/graphql/schema/directive/include.rb +2 -2
  149. data/lib/graphql/schema/directive/one_of.rb +12 -0
  150. data/lib/graphql/schema/directive/skip.rb +2 -2
  151. data/lib/graphql/schema/directive/transform.rb +14 -2
  152. data/lib/graphql/schema/directive.rb +134 -15
  153. data/lib/graphql/schema/enum.rb +137 -39
  154. data/lib/graphql/schema/enum_value.rb +20 -23
  155. data/lib/graphql/schema/field/connection_extension.rb +50 -20
  156. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  157. data/lib/graphql/schema/field.rb +503 -331
  158. data/lib/graphql/schema/field_extension.rb +89 -2
  159. data/lib/graphql/schema/find_inherited_value.rb +17 -1
  160. data/lib/graphql/schema/finder.rb +16 -14
  161. data/lib/graphql/schema/input_object.rb +182 -60
  162. data/lib/graphql/schema/interface.rb +24 -49
  163. data/lib/graphql/schema/introspection_system.rb +103 -37
  164. data/lib/graphql/schema/late_bound_type.rb +9 -2
  165. data/lib/graphql/schema/list.rb +61 -3
  166. data/lib/graphql/schema/loader.rb +144 -96
  167. data/lib/graphql/schema/member/base_dsl_methods.rb +41 -37
  168. data/lib/graphql/schema/member/build_type.rb +24 -15
  169. data/lib/graphql/schema/member/has_arguments.rb +310 -26
  170. data/lib/graphql/schema/member/has_ast_node.rb +32 -0
  171. data/lib/graphql/schema/member/has_deprecation_reason.rb +24 -0
  172. data/lib/graphql/schema/member/has_directives.rb +120 -0
  173. data/lib/graphql/schema/member/has_fields.rb +112 -34
  174. data/lib/graphql/schema/member/has_interfaces.rb +129 -0
  175. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  176. data/lib/graphql/schema/member/has_validators.rb +57 -0
  177. data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
  178. data/lib/graphql/schema/member/type_system_helpers.rb +20 -3
  179. data/lib/graphql/schema/member/validates_input.rb +33 -0
  180. data/lib/graphql/schema/member.rb +11 -6
  181. data/lib/graphql/schema/mutation.rb +4 -9
  182. data/lib/graphql/schema/non_null.rb +34 -4
  183. data/lib/graphql/schema/object.rb +36 -60
  184. data/lib/graphql/schema/printer.rb +16 -35
  185. data/lib/graphql/schema/relay_classic_mutation.rb +91 -44
  186. data/lib/graphql/schema/resolver/has_payload_type.rb +51 -11
  187. data/lib/graphql/schema/resolver.rb +147 -94
  188. data/lib/graphql/schema/scalar.rb +40 -15
  189. data/lib/graphql/schema/subscription.rb +60 -31
  190. data/lib/graphql/schema/timeout.rb +45 -35
  191. data/lib/graphql/schema/type_expression.rb +21 -13
  192. data/lib/graphql/schema/type_membership.rb +23 -6
  193. data/lib/graphql/schema/union.rb +49 -15
  194. data/lib/graphql/schema/unique_within_type.rb +1 -2
  195. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  196. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  197. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  198. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  199. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  200. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  201. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  202. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  203. data/lib/graphql/schema/validator.rb +171 -0
  204. data/lib/graphql/schema/warden.rb +211 -35
  205. data/lib/graphql/schema/wrapper.rb +0 -5
  206. data/lib/graphql/schema.rb +833 -889
  207. data/lib/graphql/static_validation/all_rules.rb +3 -0
  208. data/lib/graphql/static_validation/base_visitor.rb +21 -31
  209. data/lib/graphql/static_validation/definition_dependencies.rb +7 -2
  210. data/lib/graphql/static_validation/error.rb +3 -1
  211. data/lib/graphql/static_validation/literal_validator.rb +69 -26
  212. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +45 -83
  213. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +22 -6
  214. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +35 -26
  215. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  216. data/lib/graphql/static_validation/rules/directives_are_defined.rb +12 -6
  217. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +14 -14
  218. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
  219. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
  220. data/lib/graphql/static_validation/rules/fields_will_merge.rb +94 -51
  221. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  222. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  223. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  224. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  225. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  226. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  227. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  228. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  229. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  230. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -2
  231. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +9 -10
  232. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +13 -7
  233. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
  234. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -14
  235. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  236. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
  237. data/lib/graphql/static_validation/type_stack.rb +2 -2
  238. data/lib/graphql/static_validation/validation_context.rb +13 -3
  239. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  240. data/lib/graphql/static_validation/validator.rb +32 -20
  241. data/lib/graphql/static_validation.rb +1 -2
  242. data/lib/graphql/string_encoding_error.rb +13 -3
  243. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +129 -22
  244. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  245. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +58 -0
  246. data/lib/graphql/subscriptions/event.rb +84 -35
  247. data/lib/graphql/subscriptions/instrumentation.rb +0 -47
  248. data/lib/graphql/subscriptions/serialize.rb +53 -6
  249. data/lib/graphql/subscriptions.rb +137 -57
  250. data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
  251. data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
  252. data/lib/graphql/tracing/appoptics_trace.rb +231 -0
  253. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  254. data/lib/graphql/tracing/appsignal_trace.rb +71 -0
  255. data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
  256. data/lib/graphql/tracing/data_dog_trace.rb +148 -0
  257. data/lib/graphql/tracing/data_dog_tracing.rb +34 -2
  258. data/lib/graphql/tracing/new_relic_trace.rb +75 -0
  259. data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
  260. data/lib/graphql/tracing/notifications_trace.rb +41 -0
  261. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  262. data/lib/graphql/tracing/platform_trace.rb +107 -0
  263. data/lib/graphql/tracing/platform_tracing.rb +76 -35
  264. data/lib/graphql/tracing/prometheus_trace.rb +89 -0
  265. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  266. data/lib/graphql/tracing/prometheus_tracing.rb +11 -3
  267. data/lib/graphql/tracing/scout_trace.rb +72 -0
  268. data/lib/graphql/tracing/scout_tracing.rb +19 -0
  269. data/lib/graphql/tracing/statsd_trace.rb +56 -0
  270. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  271. data/lib/graphql/tracing.rb +143 -67
  272. data/lib/graphql/type_kinds.rb +6 -3
  273. data/lib/graphql/types/big_int.rb +5 -1
  274. data/lib/graphql/types/int.rb +10 -3
  275. data/lib/graphql/types/iso_8601_date.rb +20 -9
  276. data/lib/graphql/types/iso_8601_date_time.rb +36 -10
  277. data/lib/graphql/types/relay/base_connection.rb +18 -90
  278. data/lib/graphql/types/relay/base_edge.rb +2 -34
  279. data/lib/graphql/types/relay/connection_behaviors.rb +176 -0
  280. data/lib/graphql/types/relay/edge_behaviors.rb +75 -0
  281. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  282. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  283. data/lib/graphql/types/relay/node.rb +2 -4
  284. data/lib/graphql/types/relay/node_behaviors.rb +25 -0
  285. data/lib/graphql/types/relay/page_info.rb +2 -14
  286. data/lib/graphql/types/relay/page_info_behaviors.rb +30 -0
  287. data/lib/graphql/types/relay.rb +10 -5
  288. data/lib/graphql/types/string.rb +8 -2
  289. data/lib/graphql/unauthorized_error.rb +2 -2
  290. data/lib/graphql/unresolved_type_error.rb +2 -2
  291. data/lib/graphql/version.rb +1 -1
  292. data/lib/graphql.rb +60 -66
  293. data/readme.md +3 -6
  294. metadata +124 -236
  295. data/lib/graphql/analysis/analyze_query.rb +0 -91
  296. data/lib/graphql/analysis/field_usage.rb +0 -45
  297. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  298. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  299. data/lib/graphql/analysis/query_complexity.rb +0 -88
  300. data/lib/graphql/analysis/query_depth.rb +0 -43
  301. data/lib/graphql/analysis/reducer_state.rb +0 -48
  302. data/lib/graphql/argument.rb +0 -159
  303. data/lib/graphql/authorization.rb +0 -82
  304. data/lib/graphql/backwards_compatibility.rb +0 -60
  305. data/lib/graphql/base_type.rb +0 -226
  306. data/lib/graphql/boolean_type.rb +0 -2
  307. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  308. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  309. data/lib/graphql/compatibility/execution_specification.rb +0 -435
  310. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  311. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -213
  312. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -91
  313. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  314. data/lib/graphql/compatibility/query_parser_specification.rb +0 -264
  315. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -680
  316. data/lib/graphql/compatibility.rb +0 -5
  317. data/lib/graphql/define/assign_argument.rb +0 -12
  318. data/lib/graphql/define/assign_connection.rb +0 -13
  319. data/lib/graphql/define/assign_enum_value.rb +0 -18
  320. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  321. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  322. data/lib/graphql/define/assign_object_field.rb +0 -42
  323. data/lib/graphql/define/defined_object_proxy.rb +0 -50
  324. data/lib/graphql/define/instance_definable.rb +0 -300
  325. data/lib/graphql/define/no_definition_error.rb +0 -7
  326. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  327. data/lib/graphql/define/type_definer.rb +0 -31
  328. data/lib/graphql/define.rb +0 -31
  329. data/lib/graphql/deprecated_dsl.rb +0 -42
  330. data/lib/graphql/directive/deprecated_directive.rb +0 -13
  331. data/lib/graphql/directive/include_directive.rb +0 -2
  332. data/lib/graphql/directive/skip_directive.rb +0 -2
  333. data/lib/graphql/directive.rb +0 -104
  334. data/lib/graphql/enum_type.rb +0 -193
  335. data/lib/graphql/execution/execute.rb +0 -326
  336. data/lib/graphql/execution/flatten.rb +0 -40
  337. data/lib/graphql/execution/instrumentation.rb +0 -92
  338. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  339. data/lib/graphql/execution/lazy/resolve.rb +0 -91
  340. data/lib/graphql/execution/typecast.rb +0 -50
  341. data/lib/graphql/field/resolve.rb +0 -59
  342. data/lib/graphql/field.rb +0 -330
  343. data/lib/graphql/float_type.rb +0 -2
  344. data/lib/graphql/function.rb +0 -153
  345. data/lib/graphql/id_type.rb +0 -2
  346. data/lib/graphql/input_object_type.rb +0 -154
  347. data/lib/graphql/int_type.rb +0 -2
  348. data/lib/graphql/interface_type.rb +0 -86
  349. data/lib/graphql/internal_representation/document.rb +0 -27
  350. data/lib/graphql/internal_representation/node.rb +0 -206
  351. data/lib/graphql/internal_representation/print.rb +0 -51
  352. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  353. data/lib/graphql/internal_representation/scope.rb +0 -88
  354. data/lib/graphql/internal_representation/visit.rb +0 -36
  355. data/lib/graphql/internal_representation.rb +0 -7
  356. data/lib/graphql/language/lexer.rl +0 -258
  357. data/lib/graphql/list_type.rb +0 -80
  358. data/lib/graphql/literal_validation_error.rb +0 -6
  359. data/lib/graphql/non_null_type.rb +0 -81
  360. data/lib/graphql/object_type.rb +0 -141
  361. data/lib/graphql/query/arguments.rb +0 -187
  362. data/lib/graphql/query/arguments_cache.rb +0 -25
  363. data/lib/graphql/query/executor.rb +0 -53
  364. data/lib/graphql/query/literal_input.rb +0 -116
  365. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  366. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  367. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  368. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  369. data/lib/graphql/query/serial_execution.rb +0 -39
  370. data/lib/graphql/relay/array_connection.rb +0 -85
  371. data/lib/graphql/relay/base_connection.rb +0 -172
  372. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  373. data/lib/graphql/relay/connection_resolve.rb +0 -43
  374. data/lib/graphql/relay/connection_type.rb +0 -40
  375. data/lib/graphql/relay/edge.rb +0 -27
  376. data/lib/graphql/relay/edge_type.rb +0 -18
  377. data/lib/graphql/relay/edges_instrumentation.rb +0 -40
  378. data/lib/graphql/relay/global_id_resolve.rb +0 -18
  379. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  380. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  381. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  382. data/lib/graphql/relay/mutation/result.rb +0 -38
  383. data/lib/graphql/relay/mutation.rb +0 -190
  384. data/lib/graphql/relay/node.rb +0 -36
  385. data/lib/graphql/relay/page_info.rb +0 -7
  386. data/lib/graphql/relay/relation_connection.rb +0 -190
  387. data/lib/graphql/relay/type_extensions.rb +0 -30
  388. data/lib/graphql/scalar_type.rb +0 -133
  389. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  390. data/lib/graphql/schema/default_parse_error.rb +0 -10
  391. data/lib/graphql/schema/default_type_error.rb +0 -15
  392. data/lib/graphql/schema/member/accepts_definition.rb +0 -152
  393. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -26
  394. data/lib/graphql/schema/member/instrumentation.rb +0 -132
  395. data/lib/graphql/schema/middleware_chain.rb +0 -82
  396. data/lib/graphql/schema/possible_types.rb +0 -39
  397. data/lib/graphql/schema/rescue_middleware.rb +0 -60
  398. data/lib/graphql/schema/timeout_middleware.rb +0 -86
  399. data/lib/graphql/schema/traversal.rb +0 -228
  400. data/lib/graphql/schema/validation.rb +0 -303
  401. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  402. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  403. data/lib/graphql/string_type.rb +0 -2
  404. data/lib/graphql/subscriptions/subscription_root.rb +0 -66
  405. data/lib/graphql/tracing/skylight_tracing.rb +0 -62
  406. data/lib/graphql/types/relay/base_field.rb +0 -22
  407. data/lib/graphql/types/relay/base_interface.rb +0 -29
  408. data/lib/graphql/types/relay/base_object.rb +0 -26
  409. data/lib/graphql/types/relay/node_field.rb +0 -43
  410. data/lib/graphql/types/relay/nodes_field.rb +0 -45
  411. data/lib/graphql/union_type.rb +0 -128
  412. data/lib/graphql/upgrader/member.rb +0 -936
  413. data/lib/graphql/upgrader/schema.rb +0 -37
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Validator
6
+ # Use this validator to require _one_ of the named arguments to be present.
7
+ # Or, use Arrays of symbols to name a valid _set_ of arguments.
8
+ #
9
+ # (This is for specifying mutually exclusive sets of arguments.)
10
+ #
11
+ # @example Require exactly one of these arguments
12
+ #
13
+ # field :update_amount, IngredientAmount, null: false do
14
+ # argument :ingredient_id, ID, required: true
15
+ # argument :cups, Integer, required: false
16
+ # argument :tablespoons, Integer, required: false
17
+ # argument :teaspoons, Integer, required: false
18
+ # validates required: { one_of: [:cups, :tablespoons, :teaspoons] }
19
+ # end
20
+ #
21
+ # @example Require one of these _sets_ of arguments
22
+ #
23
+ # field :find_object, Node, null: true do
24
+ # argument :node_id, ID, required: false
25
+ # argument :object_type, String, required: false
26
+ # argument :object_id, Integer, required: false
27
+ # # either a global `node_id` or an `object_type`/`object_id` pair is required:
28
+ # validates required: { one_of: [:node_id, [:object_type, :object_id]] }
29
+ # end
30
+ #
31
+ # @example require _some_ value for an argument, even if it's null
32
+ # field :update_settings, AccountSettings do
33
+ # # `required: :nullable` means this argument must be given, but may be `null`
34
+ # argument :age, Integer, required: :nullable
35
+ # end
36
+ #
37
+ class RequiredValidator < Validator
38
+ # @param one_of [Symbol, Array<Symbol>] An argument, or a list of arguments, that represents a valid set of inputs for this field
39
+ # @param message [String]
40
+ def initialize(one_of: nil, argument: nil, message: "%{validated} has the wrong arguments", **default_options)
41
+ @one_of = if one_of
42
+ one_of
43
+ elsif argument
44
+ [argument]
45
+ else
46
+ raise ArgumentError, "`one_of:` or `argument:` must be given in `validates required: {...}`"
47
+ end
48
+ @message = message
49
+ super(**default_options)
50
+ end
51
+
52
+ def validate(_object, _context, value)
53
+ matched_conditions = 0
54
+
55
+ if !value.nil?
56
+ @one_of.each do |one_of_condition|
57
+ case one_of_condition
58
+ when Symbol
59
+ if value.key?(one_of_condition)
60
+ matched_conditions += 1
61
+ end
62
+ when Array
63
+ if one_of_condition.all? { |k| value.key?(k) }
64
+ matched_conditions += 1
65
+ break
66
+ end
67
+ else
68
+ raise ArgumentError, "Unknown one_of condition: #{one_of_condition.inspect}"
69
+ end
70
+ end
71
+ end
72
+
73
+ if matched_conditions == 1
74
+ nil # OK
75
+ else
76
+ @message
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Validator
6
+ # The thing being validated
7
+ # @return [GraphQL::Schema::Argument, GraphQL::Schema::Field, GraphQL::Schema::Resolver, Class<GraphQL::Schema::InputObject>]
8
+ attr_reader :validated
9
+
10
+ # @param validated [GraphQL::Schema::Argument, GraphQL::Schema::Field, GraphQL::Schema::Resolver, Class<GraphQL::Schema::InputObject>] The argument or argument owner this validator is attached to
11
+ # @param allow_blank [Boolean] if `true`, then objects that respond to `.blank?` and return true for `.blank?` will skip this validation
12
+ # @param allow_null [Boolean] if `true`, then incoming `null`s will skip this validation
13
+ def initialize(validated:, allow_blank: false, allow_null: false)
14
+ @validated = validated
15
+ @allow_blank = allow_blank
16
+ @allow_null = allow_null
17
+ end
18
+
19
+ # @param object [Object] The application object that this argument's field is being resolved for
20
+ # @param context [GraphQL::Query::Context]
21
+ # @param value [Object] The client-provided value for this argument (after parsing and coercing by the input type)
22
+ # @return [nil, Array<String>, String] Error message or messages to add
23
+ def validate(object, context, value)
24
+ raise GraphQL::RequiredImplementationMissingError, "Validator classes should implement #validate"
25
+ end
26
+
27
+ # This is like `String#%`, but it supports the case that only some of `string`'s
28
+ # values are present in `substitutions`
29
+ def partial_format(string, substitutions)
30
+ substitutions.each do |key, value|
31
+ sub_v = value.is_a?(String) ? value : value.to_s
32
+ string = string.gsub("%{#{key}}", sub_v)
33
+ end
34
+ string
35
+ end
36
+
37
+ # @return [Boolean] `true` if `value` is `nil` and this validator has `allow_null: true` or if value is `.blank?` and this validator has `allow_blank: true`
38
+ def permitted_empty_value?(value)
39
+ (value.nil? && @allow_null) ||
40
+ (@allow_blank && value.respond_to?(:blank?) && value.blank?)
41
+ end
42
+
43
+ # @param schema_member [GraphQL::Schema::Field, GraphQL::Schema::Argument, Class<GraphQL::Schema::InputObject>]
44
+ # @param validates_hash [Hash{Symbol => Hash}, Hash{Class => Hash} nil] A configuration passed as `validates:`
45
+ # @return [Array<Validator>]
46
+ def self.from_config(schema_member, validates_hash)
47
+ if validates_hash.nil? || validates_hash.empty?
48
+ EMPTY_ARRAY
49
+ else
50
+ validates_hash = validates_hash.dup
51
+
52
+ default_options = {}
53
+ if validates_hash[:allow_null]
54
+ default_options[:allow_null] = validates_hash.delete(:allow_null)
55
+ end
56
+ if validates_hash[:allow_blank]
57
+ default_options[:allow_blank] = validates_hash.delete(:allow_blank)
58
+ end
59
+
60
+ # allow_nil or allow_blank are the _only_ validations:
61
+ if validates_hash.empty?
62
+ validates_hash = default_options
63
+ end
64
+
65
+ validates_hash.map do |validator_name, options|
66
+ validator_class = case validator_name
67
+ when Class
68
+ validator_name
69
+ else
70
+ all_validators[validator_name] || raise(ArgumentError, "unknown validation: #{validator_name.inspect}")
71
+ end
72
+ if options.is_a?(Hash)
73
+ validator_class.new(validated: schema_member, **(default_options.merge(options)))
74
+ else
75
+ validator_class.new(options, validated: schema_member, **default_options)
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ # Add `validator_class` to be initialized when `validates:` is given `name`.
82
+ # (It's initialized with whatever options are given by the key `name`).
83
+ # @param name [Symbol]
84
+ # @param validator_class [Class]
85
+ # @return [void]
86
+ def self.install(name, validator_class)
87
+ all_validators[name] = validator_class
88
+ nil
89
+ end
90
+
91
+ # Remove whatever validator class is {.install}ed at `name`, if there is one
92
+ # @param name [Symbol]
93
+ # @return [void]
94
+ def self.uninstall(name)
95
+ all_validators.delete(name)
96
+ nil
97
+ end
98
+
99
+ class << self
100
+ attr_accessor :all_validators
101
+ end
102
+
103
+ self.all_validators = {}
104
+
105
+ include Schema::FindInheritedValue::EmptyObjects
106
+
107
+ class ValidationFailedError < GraphQL::ExecutionError
108
+ attr_reader :errors
109
+
110
+ def initialize(errors:)
111
+ @errors = errors
112
+ super(errors.join(", "))
113
+ end
114
+ end
115
+
116
+ # @param validators [Array<Validator>]
117
+ # @param object [Object]
118
+ # @param context [Query::Context]
119
+ # @param value [Object]
120
+ # @return [void]
121
+ # @raises [ValidationFailedError]
122
+ def self.validate!(validators, object, context, value, as: nil)
123
+ # Assuming the default case is no errors, reduce allocations in that case.
124
+ # This will be replaced with a mutable array if we actually get any errors.
125
+ all_errors = EMPTY_ARRAY
126
+
127
+ validators.each do |validator|
128
+ validated = as || validator.validated
129
+ errors = validator.validate(object, context, value)
130
+ if errors &&
131
+ (errors.is_a?(Array) && errors != EMPTY_ARRAY) ||
132
+ (errors.is_a?(String))
133
+ if all_errors.frozen? # It's empty
134
+ all_errors = []
135
+ end
136
+ interpolation_vars = { validated: validated.graphql_name }
137
+ if errors.is_a?(String)
138
+ all_errors << (errors % interpolation_vars)
139
+ else
140
+ errors = errors.map { |e| e % interpolation_vars }
141
+ all_errors.concat(errors)
142
+ end
143
+ end
144
+ end
145
+
146
+ if all_errors.any?
147
+ raise ValidationFailedError.new(errors: all_errors)
148
+ end
149
+ nil
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+
156
+ require "graphql/schema/validator/length_validator"
157
+ GraphQL::Schema::Validator.install(:length, GraphQL::Schema::Validator::LengthValidator)
158
+ require "graphql/schema/validator/numericality_validator"
159
+ GraphQL::Schema::Validator.install(:numericality, GraphQL::Schema::Validator::NumericalityValidator)
160
+ require "graphql/schema/validator/format_validator"
161
+ GraphQL::Schema::Validator.install(:format, GraphQL::Schema::Validator::FormatValidator)
162
+ require "graphql/schema/validator/inclusion_validator"
163
+ GraphQL::Schema::Validator.install(:inclusion, GraphQL::Schema::Validator::InclusionValidator)
164
+ require "graphql/schema/validator/exclusion_validator"
165
+ GraphQL::Schema::Validator.install(:exclusion, GraphQL::Schema::Validator::ExclusionValidator)
166
+ require "graphql/schema/validator/required_validator"
167
+ GraphQL::Schema::Validator.install(:required, GraphQL::Schema::Validator::RequiredValidator)
168
+ require "graphql/schema/validator/allow_null_validator"
169
+ GraphQL::Schema::Validator.install(:allow_null, GraphQL::Schema::Validator::AllowNullValidator)
170
+ require "graphql/schema/validator/allow_blank_validator"
171
+ GraphQL::Schema::Validator.install(:allow_blank, GraphQL::Schema::Validator::AllowBlankValidator)
@@ -10,7 +10,7 @@ module GraphQL
10
10
  # should go through a warden. If you access the schema directly,
11
11
  # you may show a client something that it shouldn't be allowed to see.
12
12
  #
13
- # @example Hidding private fields
13
+ # @example Hiding private fields
14
14
  # private_members = -> (member, ctx) { member.metadata[:private] }
15
15
  # result = Schema.execute(query_string, except: private_members)
16
16
  #
@@ -37,26 +37,92 @@ module GraphQL
37
37
  #
38
38
  # @api private
39
39
  class Warden
40
+ def self.from_context(context)
41
+ (context.respond_to?(:warden) && context.warden) || PassThruWarden
42
+ end
43
+
44
+ # @param visibility_method [Symbol] a Warden method to call for this entry
45
+ # @param entry [Object, Array<Object>] One or more definitions for a given name in a GraphQL Schema
46
+ # @param context [GraphQL::Query::Context]
47
+ # @param warden [Warden]
48
+ # @return [Object] `entry` or one of `entry`'s items if exactly one of them is visible for this context
49
+ # @return [nil] If neither `entry` nor any of `entry`'s items are visible for this context
50
+ def self.visible_entry?(visibility_method, entry, context, warden = Warden.from_context(context))
51
+ if entry.is_a?(Array)
52
+ visible_item = nil
53
+ entry.each do |item|
54
+ if warden.public_send(visibility_method, item, context)
55
+ if visible_item.nil?
56
+ visible_item = item
57
+ else
58
+ raise DuplicateNamesError.new(
59
+ duplicated_name: item.path, duplicated_definition_1: visible_item.inspect, duplicated_definition_2: item.inspect
60
+ )
61
+ end
62
+ end
63
+ end
64
+ visible_item
65
+ elsif warden.public_send(visibility_method, entry, context)
66
+ entry
67
+ else
68
+ nil
69
+ end
70
+ end
71
+
72
+ # This is used when a caller provides a Hash for context.
73
+ # We want to call the schema's hooks, but we don't have a full-blown warden.
74
+ # The `context` arguments to these methods exist purely to simplify the code that
75
+ # calls methods on this object, so it will have everything it needs.
76
+ class PassThruWarden
77
+ class << self
78
+ def visible_field?(field, ctx); field.visible?(ctx); end
79
+ def visible_argument?(arg, ctx); arg.visible?(ctx); end
80
+ def visible_type?(type, ctx); type.visible?(ctx); end
81
+ def visible_enum_value?(ev, ctx); ev.visible?(ctx); end
82
+ def visible_type_membership?(tm, ctx); tm.visible?(ctx); end
83
+ def interface_type_memberships(obj_t, ctx); obj_t.interface_type_memberships; end
84
+ def arguments(owner, ctx); owner.arguments(ctx); end
85
+ end
86
+ end
87
+
40
88
  # @param filter [<#call(member)>] Objects are hidden when `.call(member, ctx)` returns true
41
89
  # @param context [GraphQL::Query::Context]
42
90
  # @param schema [GraphQL::Schema]
43
- # @param deep_check [Boolean]
44
91
  def initialize(filter, context:, schema:)
45
92
  @schema = schema
93
+ # Cache these to avoid repeated hits to the inheritance chain when one isn't present
94
+ @query = @schema.query
95
+ @mutation = @schema.mutation
96
+ @subscription = @schema.subscription
46
97
  @context = context
47
- @visibility_cache = read_through { |m| filter.call(m, @context) }
98
+ @visibility_cache = read_through { |m| filter.call(m, context) }
99
+ # Initialize all ivars to improve object shape consistency:
100
+ @types = @visible_types = @reachable_types = @visible_parent_fields =
101
+ @visible_possible_types = @visible_fields = @visible_arguments = @visible_enum_arrays =
102
+ @visible_enum_values = @visible_interfaces = @type_visibility = @type_memberships =
103
+ @visible_and_reachable_type = @unions = @unfiltered_interfaces = @references_to =
104
+ @reachable_type_set =
105
+ nil
48
106
  end
49
107
 
50
- # @return [Array<GraphQL::BaseType>] Visible types in the schema
108
+ # @return [Hash<String, GraphQL::BaseType>] Visible types in the schema
51
109
  def types
52
- @types ||= @schema.types.each_value.select { |t| visible_type?(t) }
110
+ @types ||= begin
111
+ vis_types = {}
112
+ @schema.types(@context).each do |n, t|
113
+ if visible_and_reachable_type?(t)
114
+ vis_types[n] = t
115
+ end
116
+ end
117
+ vis_types
118
+ end
53
119
  end
54
120
 
55
121
  # @return [GraphQL::BaseType, nil] The type named `type_name`, if it exists (else `nil`)
56
122
  def get_type(type_name)
57
123
  @visible_types ||= read_through do |name|
58
- type_defn = @schema.types.fetch(name, nil)
59
- if type_defn && visible_type?(type_defn)
124
+ type_defn = @schema.get_type(name, @context)
125
+ if type_defn && visible_and_reachable_type?(type_defn)
60
126
  type_defn
61
127
  else
62
128
  nil
@@ -73,17 +139,16 @@ module GraphQL
73
139
 
74
140
  # @return Boolean True if the type is visible and reachable in the schema
75
141
  def reachable_type?(type_name)
76
- type = get_type(type_name)
142
+ type = get_type(type_name) # rubocop:disable Development/ContextIsPassedCop -- `self` is query-aware
77
143
  type && reachable_type_set.include?(type)
78
144
  end
79
145
 
80
146
  # @return [GraphQL::Field, nil] The field named `field_name` on `parent_type`, if it exists
81
147
  def get_field(parent_type, field_name)
82
-
83
148
  @visible_parent_fields ||= read_through do |type|
84
149
  read_through do |f_name|
85
- field_defn = @schema.get_field(type, f_name)
86
- if field_defn && visible_field?(field_defn)
150
+ field_defn = @schema.get_field(type, f_name, @context)
151
+ if field_defn && visible_field?(field_defn, nil, type)
87
152
  field_defn
88
153
  else
89
154
  nil
@@ -94,35 +159,55 @@ module GraphQL
94
159
  @visible_parent_fields[parent_type][field_name]
95
160
  end
96
161
 
162
+ # @return [GraphQL::Argument, nil] The argument named `argument_name` on `parent_type`, if it exists and is visible
163
+ def get_argument(parent_type, argument_name)
164
+ argument = parent_type.get_argument(argument_name, @context)
165
+ return argument if argument && visible_argument?(argument, @context)
166
+ end
167
+
97
168
  # @return [Array<GraphQL::BaseType>] The types which may be member of `type_defn`
98
169
  def possible_types(type_defn)
99
- @visible_possible_types ||= read_through { |type_defn| @schema.possible_types(type_defn, @context).select { |t| visible_type?(t) } }
170
+ @visible_possible_types ||= read_through { |type_defn|
171
+ pt = @schema.possible_types(type_defn, @context)
172
+ pt.select { |t| visible_and_reachable_type?(t) }
173
+ }
100
174
  @visible_possible_types[type_defn]
101
175
  end
102
176
 
103
177
  # @param type_defn [GraphQL::ObjectType, GraphQL::InterfaceType]
104
178
  # @return [Array<GraphQL::Field>] Fields on `type_defn`
105
179
  def fields(type_defn)
106
- @visible_fields ||= read_through { |t| @schema.get_fields(t).each_value.select { |f| visible_field?(f) } }
180
+ @visible_fields ||= read_through { |t| @schema.get_fields(t, @context).values }
107
181
  @visible_fields[type_defn]
108
182
  end
109
183
 
110
184
  # @param argument_owner [GraphQL::Field, GraphQL::InputObjectType]
111
185
  # @return [Array<GraphQL::Argument>] Visible arguments on `argument_owner`
112
- def arguments(argument_owner)
113
- @visible_arguments ||= read_through { |o| o.arguments.each_value.select { |a| visible_field?(a) } }
186
+ def arguments(argument_owner, ctx = nil)
187
+ @visible_arguments ||= read_through { |o| o.arguments(@context).each_value.select { |a| visible_argument?(a, @context) } }
114
188
  @visible_arguments[argument_owner]
115
189
  end
116
190
 
117
191
  # @return [Array<GraphQL::EnumType::EnumValue>] Visible members of `enum_defn`
118
192
  def enum_values(enum_defn)
119
- @visible_enum_values ||= read_through { |e| e.values.each_value.select { |enum_value_defn| visible?(enum_value_defn) } }
120
- @visible_enum_values[enum_defn]
193
+ @visible_enum_arrays ||= read_through { |e|
194
+ values = e.enum_values(@context)
195
+ if values.size == 0
196
+ raise GraphQL::Schema::Enum::MissingValuesError.new(e)
197
+ end
198
+ values
199
+ }
200
+ @visible_enum_arrays[enum_defn]
201
+ end
202
+
203
+ def visible_enum_value?(enum_value, _ctx = nil)
204
+ @visible_enum_values ||= read_through { |ev| visible?(ev) }
205
+ @visible_enum_values[enum_value]
121
206
  end
122
207
 
123
208
  # @return [Array<GraphQL::InterfaceType>] Visible interfaces implemented by `obj_type`
124
209
  def interfaces(obj_type)
125
- @visible_interfaces ||= read_through { |t| t.interfaces.select { |i| visible?(i) } }
210
+ @visible_interfaces ||= read_through { |t| t.interfaces(@context).select { |i| visible_type?(i) } }
126
211
  @visible_interfaces[obj_type]
127
212
  end
128
213
 
@@ -139,40 +224,112 @@ module GraphQL
139
224
  end
140
225
  end
141
226
 
227
+ # @param owner [Class, Module] If provided, confirm that field has the given owner.
228
+ def visible_field?(field_defn, _ctx = nil, owner = field_defn.owner)
229
+ # This field is visible in its own right
230
+ visible?(field_defn) &&
231
+ # This field's return type is visible
232
+ visible_and_reachable_type?(field_defn.type.unwrap) &&
233
+ # This field is either defined on this object type,
234
+ # or the interface it's inherited from is also visible
235
+ ((field_defn.respond_to?(:owner) && field_defn.owner == owner) || field_on_visible_interface?(field_defn, owner))
236
+ end
237
+
238
+ def visible_argument?(arg_defn, _ctx = nil)
239
+ visible?(arg_defn) && visible_and_reachable_type?(arg_defn.type.unwrap)
240
+ end
241
+
242
+ def visible_type?(type_defn, _ctx = nil)
243
+ @type_visibility ||= read_through { |type_defn| visible?(type_defn) }
244
+ @type_visibility[type_defn]
245
+ end
246
+
247
+ def visible_type_membership?(type_membership, _ctx = nil)
248
+ visible?(type_membership)
249
+ end
250
+
251
+ def interface_type_memberships(obj_type, _ctx = nil)
252
+ @type_memberships ||= read_through do |obj_t|
253
+ obj_t.interface_type_memberships
254
+ end
255
+ @type_memberships[obj_type]
256
+ end
257
+
142
258
  private
143
259
 
260
+ def visible_and_reachable_type?(type_defn)
261
+ @visible_and_reachable_type ||= read_through do |type_defn|
262
+ next false unless visible_type?(type_defn)
263
+ next true if root_type?(type_defn) || type_defn.introspection?
264
+
265
+ if type_defn.kind.union?
266
+ visible_possible_types?(type_defn) && (referenced?(type_defn) || orphan_type?(type_defn))
267
+ elsif type_defn.kind.interface?
268
+ visible_possible_types?(type_defn)
269
+ else
270
+ referenced?(type_defn) || visible_abstract_type?(type_defn)
271
+ end
272
+ end
273
+
274
+ @visible_and_reachable_type[type_defn]
275
+ end
276
+
144
277
  def union_memberships(obj_type)
145
278
  @unions ||= read_through { |obj_type| @schema.union_memberships(obj_type).select { |u| visible?(u) } }
146
279
  @unions[obj_type]
147
280
  end
148
281
 
149
- def visible_field?(field_defn)
150
- visible?(field_defn) && visible_type?(field_defn.type.unwrap)
282
+ # We need this to tell whether a field was inherited by an interface
283
+ # even when that interface is hidden from `#interfaces`
284
+ def unfiltered_interfaces(type_defn)
285
+ @unfiltered_interfaces ||= read_through(&:interfaces)
286
+ @unfiltered_interfaces[type_defn]
151
287
  end
152
288
 
153
- def visible_type?(type_defn)
154
- return false unless visible?(type_defn)
155
- return true if root_type?(type_defn)
156
- return true if type_defn.introspection?
289
+ # If this field was inherited from an interface, and the field on that interface is _hidden_,
290
+ # then treat this inherited field as hidden.
291
+ # (If it _wasn't_ inherited, then don't hide it for this reason.)
292
+ def field_on_visible_interface?(field_defn, type_defn)
293
+ if type_defn.kind.object?
294
+ any_interface_has_field = false
295
+ any_interface_has_visible_field = false
296
+ ints = unfiltered_interfaces(type_defn)
297
+ ints.each do |interface_type|
298
+ if (iface_field_defn = interface_type.get_field(field_defn.graphql_name, @context))
299
+ any_interface_has_field = true
300
+
301
+ if interfaces(type_defn).include?(interface_type) && visible_field?(iface_field_defn, nil, interface_type)
302
+ any_interface_has_visible_field = true
303
+ end
304
+ end
305
+ end
157
306
 
158
- if type_defn.kind.union?
159
- visible_possible_types?(type_defn) && (referenced?(type_defn) || orphan_type?(type_defn))
160
- elsif type_defn.kind.interface?
161
- visible_possible_types?(type_defn)
307
+ if any_interface_has_field
308
+ any_interface_has_visible_field
309
+ else
310
+ # it's the object's own field
311
+ true
312
+ end
162
313
  else
163
- referenced?(type_defn) || visible_abstract_type?(type_defn)
314
+ true
164
315
  end
165
316
  end
166
317
 
167
318
  def root_type?(type_defn)
168
- @schema.root_types.include?(type_defn)
319
+ @query == type_defn ||
320
+ @mutation == type_defn ||
321
+ @subscription == type_defn
169
322
  end
170
323
 
171
324
  def referenced?(type_defn)
172
- members = @schema.references_to(type_defn.unwrap.name)
325
+ @references_to ||= @schema.references_to
326
+ graphql_name = type_defn.unwrap.graphql_name
327
+ members = @references_to[graphql_name] || NO_REFERENCES
173
328
  members.any? { |m| visible?(m) }
174
329
  end
175
330
 
331
+ NO_REFERENCES = [].freeze
332
+
176
333
  def orphan_type?(type_defn)
177
334
  @schema.orphan_types.include?(type_defn)
178
335
  end
@@ -185,7 +342,7 @@ module GraphQL
185
342
  end
186
343
 
187
344
  def visible_possible_types?(type_defn)
188
- @schema.possible_types(type_defn, @context).any? { |t| visible_type?(t) }
345
+ possible_types(type_defn).any? { |t| visible_and_reachable_type?(t) }
189
346
  end
190
347
 
191
348
  def visible?(member)
@@ -197,23 +354,42 @@ module GraphQL
197
354
  end
198
355
 
199
356
  def reachable_type_set
200
- return @reachable_type_set if defined?(@reachable_type_set)
357
+ return @reachable_type_set if @reachable_type_set
201
358
 
202
359
  @reachable_type_set = Set.new
360
+ rt_hash = {}
203
361
 
204
362
  unvisited_types = []
205
363
  ['query', 'mutation', 'subscription'].each do |op_name|
206
364
  root_type = root_type_for_operation(op_name)
207
365
  unvisited_types << root_type if root_type
208
366
  end
209
- unvisited_types.concat(@schema.introspection_system.object_types)
367
+ unvisited_types.concat(@schema.introspection_system.types.values)
368
+
369
+ directives.each do |dir_class|
370
+ arguments(dir_class).each do |arg_defn|
371
+ arg_t = arg_defn.type.unwrap
372
+ if get_type(arg_t.graphql_name) # rubocop:disable Development/ContextIsPassedCop -- `self` is query-aware
373
+ unvisited_types << arg_t
374
+ end
375
+ end
376
+ end
377
+
210
378
  @schema.orphan_types.each do |orphan_type|
211
- unvisited_types << orphan_type.graphql_definition if get_type(orphan_type.graphql_name)
379
+ if get_type(orphan_type.graphql_name) == orphan_type # rubocop:disable Development/ContextIsPassedCop -- `self` is query-aware
380
+ unvisited_types << orphan_type
381
+ end
212
382
  end
213
383
 
214
384
  until unvisited_types.empty?
215
385
  type = unvisited_types.pop
216
386
  if @reachable_type_set.add?(type)
387
+ type_by_name = rt_hash[type.graphql_name] ||= type
388
+ if type_by_name != type
389
+ raise DuplicateNamesError.new(
390
+ duplicated_name: type.graphql_name, duplicated_definition_1: type.inspect, duplicated_definition_2: type_by_name.inspect
391
+ )
392
+ end
217
393
  if type.kind.input_object?
218
394
  # recurse into visible arguments
219
395
  arguments(type).each do |argument|
@@ -3,7 +3,6 @@
3
3
  module GraphQL
4
4
  class Schema
5
5
  class Wrapper
6
- include GraphQL::Schema::Member::CachedGraphQLDefinition
7
6
  include GraphQL::Schema::Member::TypeSystemHelpers
8
7
 
9
8
  # @return [Class, Module] The inner type of this wrapping type, the type of which one or more objects may be present.
@@ -13,10 +12,6 @@ module GraphQL
13
12
  @of_type = of_type
14
13
  end
15
14
 
16
- def to_graphql
17
- raise GraphQL::RequiredImplementationMissingError
18
- end
19
-
20
15
  def unwrap
21
16
  @of_type.unwrap
22
17
  end