graphql 1.9.18 → 1.13.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (353) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +21 -10
  3. data/lib/generators/graphql/enum_generator.rb +4 -10
  4. data/lib/generators/graphql/field_extractor.rb +31 -0
  5. data/lib/generators/graphql/input_generator.rb +50 -0
  6. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  7. data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +2 -0
  8. data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +2 -0
  9. data/lib/generators/graphql/install_generator.rb +44 -7
  10. data/lib/generators/graphql/interface_generator.rb +7 -7
  11. data/lib/generators/graphql/loader_generator.rb +1 -0
  12. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  13. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  14. data/lib/generators/graphql/mutation_generator.rb +6 -30
  15. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  16. data/lib/generators/graphql/object_generator.rb +28 -12
  17. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  18. data/lib/generators/graphql/relay.rb +63 -0
  19. data/lib/generators/graphql/relay_generator.rb +21 -0
  20. data/lib/generators/graphql/scalar_generator.rb +4 -2
  21. data/lib/generators/graphql/templates/base_argument.erb +2 -0
  22. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  23. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  24. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  25. data/lib/generators/graphql/templates/base_field.erb +2 -0
  26. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  27. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  28. data/lib/generators/graphql/templates/base_object.erb +2 -0
  29. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  30. data/lib/generators/graphql/templates/base_union.erb +2 -0
  31. data/lib/generators/graphql/templates/enum.erb +7 -1
  32. data/lib/generators/graphql/templates/graphql_controller.erb +16 -12
  33. data/lib/generators/graphql/templates/input.erb +9 -0
  34. data/lib/generators/graphql/templates/interface.erb +6 -2
  35. data/lib/generators/graphql/templates/loader.erb +2 -0
  36. data/lib/generators/graphql/templates/mutation.erb +3 -1
  37. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  38. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  39. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  40. data/lib/generators/graphql/templates/node_type.erb +9 -0
  41. data/lib/generators/graphql/templates/object.erb +7 -3
  42. data/lib/generators/graphql/templates/query_type.erb +3 -3
  43. data/lib/generators/graphql/templates/scalar.erb +5 -1
  44. data/lib/generators/graphql/templates/schema.erb +22 -27
  45. data/lib/generators/graphql/templates/union.erb +6 -2
  46. data/lib/generators/graphql/type_generator.rb +47 -10
  47. data/lib/generators/graphql/union_generator.rb +5 -5
  48. data/lib/graphql/analysis/analyze_query.rb +7 -0
  49. data/lib/graphql/analysis/ast/field_usage.rb +29 -2
  50. data/lib/graphql/analysis/ast/query_complexity.rb +174 -67
  51. data/lib/graphql/analysis/ast/visitor.rb +16 -7
  52. data/lib/graphql/analysis/ast.rb +21 -11
  53. data/lib/graphql/argument.rb +8 -36
  54. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  55. data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
  56. data/lib/graphql/backtrace/table.rb +44 -5
  57. data/lib/graphql/backtrace/traced_error.rb +0 -1
  58. data/lib/graphql/backtrace/tracer.rb +40 -9
  59. data/lib/graphql/backtrace.rb +28 -19
  60. data/lib/graphql/backwards_compatibility.rb +2 -1
  61. data/lib/graphql/base_type.rb +10 -4
  62. data/lib/graphql/boolean_type.rb +1 -1
  63. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +2 -2
  64. data/lib/graphql/compatibility/execution_specification.rb +1 -0
  65. data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
  66. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +5 -9
  67. data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
  68. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
  69. data/lib/graphql/dataloader/null_dataloader.rb +22 -0
  70. data/lib/graphql/dataloader/request.rb +19 -0
  71. data/lib/graphql/dataloader/request_all.rb +19 -0
  72. data/lib/graphql/dataloader/source.rb +155 -0
  73. data/lib/graphql/dataloader.rb +308 -0
  74. data/lib/graphql/date_encoding_error.rb +16 -0
  75. data/lib/graphql/define/assign_enum_value.rb +1 -1
  76. data/lib/graphql/define/assign_global_id_field.rb +2 -2
  77. data/lib/graphql/define/assign_object_field.rb +1 -1
  78. data/lib/graphql/define/defined_object_proxy.rb +5 -8
  79. data/lib/graphql/define/instance_definable.rb +60 -110
  80. data/lib/graphql/define/type_definer.rb +5 -5
  81. data/lib/graphql/deprecated_dsl.rb +18 -5
  82. data/lib/graphql/deprecation.rb +9 -0
  83. data/lib/graphql/directive/deprecated_directive.rb +1 -12
  84. data/lib/graphql/directive/include_directive.rb +1 -1
  85. data/lib/graphql/directive/skip_directive.rb +1 -1
  86. data/lib/graphql/directive.rb +9 -6
  87. data/lib/graphql/enum_type.rb +14 -74
  88. data/lib/graphql/execution/directive_checks.rb +2 -2
  89. data/lib/graphql/execution/errors.rb +110 -8
  90. data/lib/graphql/execution/execute.rb +8 -1
  91. data/lib/graphql/execution/instrumentation.rb +1 -1
  92. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  93. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  94. data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
  95. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  96. data/lib/graphql/execution/interpreter/resolve.rb +37 -25
  97. data/lib/graphql/execution/interpreter/runtime.rb +721 -386
  98. data/lib/graphql/execution/interpreter.rb +42 -19
  99. data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
  100. data/lib/graphql/execution/lazy.rb +5 -1
  101. data/lib/graphql/execution/lookahead.rb +39 -114
  102. data/lib/graphql/execution/multiplex.rb +50 -25
  103. data/lib/graphql/field.rb +15 -119
  104. data/lib/graphql/filter.rb +1 -1
  105. data/lib/graphql/float_type.rb +1 -1
  106. data/lib/graphql/function.rb +5 -30
  107. data/lib/graphql/id_type.rb +1 -1
  108. data/lib/graphql/input_object_type.rb +9 -25
  109. data/lib/graphql/int_type.rb +1 -1
  110. data/lib/graphql/integer_decoding_error.rb +17 -0
  111. data/lib/graphql/integer_encoding_error.rb +18 -2
  112. data/lib/graphql/interface_type.rb +10 -24
  113. data/lib/graphql/internal_representation/document.rb +2 -2
  114. data/lib/graphql/internal_representation/rewrite.rb +1 -1
  115. data/lib/graphql/internal_representation/scope.rb +2 -2
  116. data/lib/graphql/internal_representation/visit.rb +2 -2
  117. data/lib/graphql/introspection/base_object.rb +2 -5
  118. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  119. data/lib/graphql/introspection/directive_type.rb +12 -6
  120. data/lib/graphql/introspection/entry_points.rb +9 -9
  121. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  122. data/lib/graphql/introspection/field_type.rb +9 -5
  123. data/lib/graphql/introspection/input_value_type.rb +41 -11
  124. data/lib/graphql/introspection/introspection_query.rb +6 -92
  125. data/lib/graphql/introspection/schema_type.rb +12 -12
  126. data/lib/graphql/introspection/type_type.rb +27 -17
  127. data/lib/graphql/introspection.rb +99 -0
  128. data/lib/graphql/invalid_null_error.rb +18 -0
  129. data/lib/graphql/language/block_string.rb +20 -5
  130. data/lib/graphql/language/cache.rb +37 -0
  131. data/lib/graphql/language/definition_slice.rb +21 -10
  132. data/lib/graphql/language/document_from_schema_definition.rb +116 -63
  133. data/lib/graphql/language/lexer.rb +53 -27
  134. data/lib/graphql/language/lexer.rl +5 -3
  135. data/lib/graphql/language/nodes.rb +67 -93
  136. data/lib/graphql/language/parser.rb +929 -896
  137. data/lib/graphql/language/parser.y +125 -102
  138. data/lib/graphql/language/printer.rb +11 -2
  139. data/lib/graphql/language/sanitized_printer.rb +222 -0
  140. data/lib/graphql/language/token.rb +0 -4
  141. data/lib/graphql/language/visitor.rb +2 -2
  142. data/lib/graphql/language.rb +3 -1
  143. data/lib/graphql/name_validator.rb +2 -7
  144. data/lib/graphql/non_null_type.rb +0 -10
  145. data/lib/graphql/object_type.rb +47 -58
  146. data/lib/graphql/pagination/active_record_relation_connection.rb +85 -0
  147. data/lib/graphql/pagination/array_connection.rb +77 -0
  148. data/lib/graphql/pagination/connection.rb +226 -0
  149. data/lib/graphql/pagination/connections.rb +160 -0
  150. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  151. data/lib/graphql/pagination/relation_connection.rb +226 -0
  152. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  153. data/lib/graphql/pagination.rb +6 -0
  154. data/lib/graphql/parse_error.rb +0 -1
  155. data/lib/graphql/query/arguments.rb +6 -4
  156. data/lib/graphql/query/arguments_cache.rb +1 -2
  157. data/lib/graphql/query/context.rb +52 -7
  158. data/lib/graphql/query/executor.rb +0 -1
  159. data/lib/graphql/query/fingerprint.rb +26 -0
  160. data/lib/graphql/query/input_validation_result.rb +32 -6
  161. data/lib/graphql/query/literal_input.rb +31 -11
  162. data/lib/graphql/query/null_context.rb +24 -8
  163. data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
  164. data/lib/graphql/query/serial_execution.rb +1 -0
  165. data/lib/graphql/query/validation_pipeline.rb +6 -4
  166. data/lib/graphql/query/variable_validation_error.rb +3 -3
  167. data/lib/graphql/query/variables.rb +50 -10
  168. data/lib/graphql/query.rb +77 -18
  169. data/lib/graphql/railtie.rb +9 -1
  170. data/lib/graphql/rake_task/validate.rb +3 -0
  171. data/lib/graphql/rake_task.rb +12 -9
  172. data/lib/graphql/relay/array_connection.rb +10 -12
  173. data/lib/graphql/relay/base_connection.rb +30 -13
  174. data/lib/graphql/relay/connection_instrumentation.rb +4 -4
  175. data/lib/graphql/relay/connection_type.rb +18 -4
  176. data/lib/graphql/relay/edge_type.rb +1 -0
  177. data/lib/graphql/relay/edges_instrumentation.rb +1 -2
  178. data/lib/graphql/relay/global_id_resolve.rb +1 -2
  179. data/lib/graphql/relay/mutation.rb +3 -87
  180. data/lib/graphql/relay/node.rb +3 -0
  181. data/lib/graphql/relay/page_info.rb +1 -1
  182. data/lib/graphql/relay/range_add.rb +27 -9
  183. data/lib/graphql/relay/relation_connection.rb +8 -10
  184. data/lib/graphql/relay/type_extensions.rb +2 -0
  185. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  186. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  187. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  188. data/lib/graphql/rubocop.rb +4 -0
  189. data/lib/graphql/scalar_type.rb +18 -60
  190. data/lib/graphql/schema/addition.rb +247 -0
  191. data/lib/graphql/schema/argument.rb +274 -18
  192. data/lib/graphql/schema/base_64_encoder.rb +2 -0
  193. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
  194. data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
  195. data/lib/graphql/schema/build_from_definition.rb +320 -219
  196. data/lib/graphql/schema/built_in_types.rb +5 -5
  197. data/lib/graphql/schema/default_type_error.rb +2 -0
  198. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  199. data/lib/graphql/schema/directive/feature.rb +1 -1
  200. data/lib/graphql/schema/directive/flagged.rb +57 -0
  201. data/lib/graphql/schema/directive/include.rb +2 -2
  202. data/lib/graphql/schema/directive/skip.rb +2 -2
  203. data/lib/graphql/schema/directive/transform.rb +14 -2
  204. data/lib/graphql/schema/directive.rb +130 -6
  205. data/lib/graphql/schema/enum.rb +121 -12
  206. data/lib/graphql/schema/enum_value.rb +24 -7
  207. data/lib/graphql/schema/field/connection_extension.rb +46 -20
  208. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  209. data/lib/graphql/schema/field.rb +465 -181
  210. data/lib/graphql/schema/field_extension.rb +89 -2
  211. data/lib/graphql/schema/find_inherited_value.rb +17 -1
  212. data/lib/graphql/schema/finder.rb +16 -14
  213. data/lib/graphql/schema/input_object.rb +172 -37
  214. data/lib/graphql/schema/interface.rb +39 -25
  215. data/lib/graphql/schema/introspection_system.rb +106 -38
  216. data/lib/graphql/schema/late_bound_type.rb +3 -2
  217. data/lib/graphql/schema/list.rb +65 -1
  218. data/lib/graphql/schema/loader.rb +145 -102
  219. data/lib/graphql/schema/member/accepts_definition.rb +15 -3
  220. data/lib/graphql/schema/member/base_dsl_methods.rb +34 -28
  221. data/lib/graphql/schema/member/build_type.rb +19 -8
  222. data/lib/graphql/schema/member/cached_graphql_definition.rb +34 -2
  223. data/lib/graphql/schema/member/has_arguments.rb +206 -13
  224. data/lib/graphql/schema/member/has_ast_node.rb +20 -0
  225. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  226. data/lib/graphql/schema/member/has_directives.rb +98 -0
  227. data/lib/graphql/schema/member/has_fields.rb +97 -32
  228. data/lib/graphql/schema/member/has_interfaces.rb +100 -0
  229. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  230. data/lib/graphql/schema/member/has_validators.rb +31 -0
  231. data/lib/graphql/schema/member/instrumentation.rb +0 -1
  232. data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
  233. data/lib/graphql/schema/member/validates_input.rb +33 -0
  234. data/lib/graphql/schema/member.rb +11 -0
  235. data/lib/graphql/schema/middleware_chain.rb +1 -1
  236. data/lib/graphql/schema/mutation.rb +4 -0
  237. data/lib/graphql/schema/non_null.rb +37 -1
  238. data/lib/graphql/schema/object.rb +51 -38
  239. data/lib/graphql/schema/possible_types.rb +9 -4
  240. data/lib/graphql/schema/printer.rb +16 -35
  241. data/lib/graphql/schema/relay_classic_mutation.rb +40 -4
  242. data/lib/graphql/schema/resolver/has_payload_type.rb +34 -4
  243. data/lib/graphql/schema/resolver.rb +133 -79
  244. data/lib/graphql/schema/scalar.rb +43 -3
  245. data/lib/graphql/schema/subscription.rb +57 -21
  246. data/lib/graphql/schema/timeout.rb +29 -15
  247. data/lib/graphql/schema/timeout_middleware.rb +3 -1
  248. data/lib/graphql/schema/traversal.rb +2 -2
  249. data/lib/graphql/schema/type_expression.rb +21 -13
  250. data/lib/graphql/schema/type_membership.rb +19 -5
  251. data/lib/graphql/schema/union.rb +44 -3
  252. data/lib/graphql/schema/unique_within_type.rb +1 -2
  253. data/lib/graphql/schema/validation.rb +14 -4
  254. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  255. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  256. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  257. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  258. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  259. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  260. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  261. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  262. data/lib/graphql/schema/validator.rb +171 -0
  263. data/lib/graphql/schema/warden.rb +193 -34
  264. data/lib/graphql/schema.rb +882 -247
  265. data/lib/graphql/static_validation/all_rules.rb +2 -0
  266. data/lib/graphql/static_validation/base_visitor.rb +17 -10
  267. data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
  268. data/lib/graphql/static_validation/error.rb +3 -1
  269. data/lib/graphql/static_validation/literal_validator.rb +51 -26
  270. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +45 -83
  271. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +22 -6
  272. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +35 -26
  273. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  274. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
  275. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -2
  276. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
  277. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
  278. data/lib/graphql/static_validation/rules/fields_will_merge.rb +94 -51
  279. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  280. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  281. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  282. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  283. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  284. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  285. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  286. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -2
  287. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +9 -10
  288. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
  289. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
  290. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -14
  291. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  292. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
  293. data/lib/graphql/static_validation/type_stack.rb +2 -2
  294. data/lib/graphql/static_validation/validation_context.rb +13 -3
  295. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  296. data/lib/graphql/static_validation/validator.rb +43 -9
  297. data/lib/graphql/static_validation.rb +1 -0
  298. data/lib/graphql/string_encoding_error.rb +13 -3
  299. data/lib/graphql/string_type.rb +1 -1
  300. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +123 -22
  301. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  302. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
  303. data/lib/graphql/subscriptions/event.rb +84 -30
  304. data/lib/graphql/subscriptions/instrumentation.rb +10 -6
  305. data/lib/graphql/subscriptions/serialize.rb +53 -6
  306. data/lib/graphql/subscriptions/subscription_root.rb +15 -5
  307. data/lib/graphql/subscriptions.rb +117 -49
  308. data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
  309. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  310. data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
  311. data/lib/graphql/tracing/data_dog_tracing.rb +32 -15
  312. data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
  313. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  314. data/lib/graphql/tracing/platform_tracing.rb +66 -10
  315. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  316. data/lib/graphql/tracing/prometheus_tracing.rb +8 -0
  317. data/lib/graphql/tracing/scout_tracing.rb +19 -0
  318. data/lib/graphql/tracing/skylight_tracing.rb +9 -1
  319. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  320. data/lib/graphql/tracing.rb +15 -35
  321. data/lib/graphql/types/big_int.rb +5 -1
  322. data/lib/graphql/types/int.rb +10 -3
  323. data/lib/graphql/types/iso_8601_date.rb +16 -8
  324. data/lib/graphql/types/iso_8601_date_time.rb +32 -10
  325. data/lib/graphql/types/relay/base_connection.rb +6 -88
  326. data/lib/graphql/types/relay/base_edge.rb +2 -34
  327. data/lib/graphql/types/relay/connection_behaviors.rb +174 -0
  328. data/lib/graphql/types/relay/default_relay.rb +31 -0
  329. data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
  330. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  331. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  332. data/lib/graphql/types/relay/node.rb +2 -4
  333. data/lib/graphql/types/relay/node_behaviors.rb +15 -0
  334. data/lib/graphql/types/relay/node_field.rb +3 -22
  335. data/lib/graphql/types/relay/nodes_field.rb +16 -18
  336. data/lib/graphql/types/relay/page_info.rb +2 -14
  337. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  338. data/lib/graphql/types/relay.rb +11 -3
  339. data/lib/graphql/types/string.rb +8 -2
  340. data/lib/graphql/unauthorized_error.rb +2 -2
  341. data/lib/graphql/union_type.rb +5 -25
  342. data/lib/graphql/unresolved_type_error.rb +2 -2
  343. data/lib/graphql/upgrader/member.rb +1 -0
  344. data/lib/graphql/upgrader/schema.rb +1 -0
  345. data/lib/graphql/version.rb +1 -1
  346. data/lib/graphql.rb +87 -31
  347. data/readme.md +3 -6
  348. metadata +126 -124
  349. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  350. data/lib/graphql/literal_validation_error.rb +0 -6
  351. data/lib/graphql/types/relay/base_field.rb +0 -22
  352. data/lib/graphql/types/relay/base_interface.rb +0 -29
  353. data/lib/graphql/types/relay/base_object.rb +0 -26
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
  require "graphql/tracing/active_support_notifications_tracing"
3
3
  require "graphql/tracing/platform_tracing"
4
+ require "graphql/tracing/appoptics_tracing"
4
5
  require "graphql/tracing/appsignal_tracing"
5
6
  require "graphql/tracing/data_dog_tracing"
6
7
  require "graphql/tracing/new_relic_tracing"
7
8
  require "graphql/tracing/scout_tracing"
8
9
  require "graphql/tracing/skylight_tracing"
10
+ require "graphql/tracing/statsd_tracing"
9
11
  require "graphql/tracing/prometheus_tracing"
10
12
 
11
13
  if defined?(PrometheusExporter::Server)
@@ -15,15 +17,13 @@ end
15
17
  module GraphQL
16
18
  # Library entry point for performance metric reporting.
17
19
  #
18
- # __Warning:__ Installing/uninstalling tracers is not thread-safe. Do it during application boot only.
19
- #
20
20
  # @example Sending custom events
21
- # GraphQL::Tracing.trace("my_custom_event", { ... }) do
21
+ # query.trace("my_custom_event", { ... }) do
22
22
  # # do stuff ...
23
23
  # end
24
24
  #
25
25
  # @example Adding a tracer to a schema
26
- # MySchema = GraphQL::Schema.define do
26
+ # class MySchema < GraphQL::Schema
27
27
  # tracer MyTracer # <= responds to .trace(key, data, &block)
28
28
  # end
29
29
  #
@@ -42,8 +42,12 @@ module GraphQL
42
42
  # execute_multiplex | `{ multiplex: GraphQL::Execution::Multiplex }`
43
43
  # execute_query | `{ query: GraphQL::Query }`
44
44
  # execute_query_lazy | `{ query: GraphQL::Query?, multiplex: GraphQL::Execution::Multiplex? }`
45
- # execute_field | `{ context: GraphQL::Query::Context::FieldResolutionContext?, owner: Class?, field: GraphQL::Schema::Field?, query: GraphQL::Query?, path: Array<String, Integer>?}`
46
- # execute_field_lazy | `{ context: GraphQL::Query::Context::FieldResolutionContext?, owner: Class?, field: GraphQL::Schema::Field?, query: GraphqL::Query?, path: Array<String, Integer>?}`
45
+ # execute_field | `{ owner: Class, field: GraphQL::Schema::Field, query: GraphQL::Query, path: Array<String, Integer>, ast_node: GraphQL::Language::Nodes::Field}`
46
+ # execute_field_lazy | `{ owner: Class, field: GraphQL::Schema::Field, query: GraphQL::Query, path: Array<String, Integer>, ast_node: GraphQL::Language::Nodes::Field}`
47
+ # authorized | `{ context: GraphQL::Query::Context, type: Class, object: Object, path: Array<String, Integer> }`
48
+ # authorized_lazy | `{ context: GraphQL::Query::Context, type: Class, object: Object, path: Array<String, Integer> }`
49
+ # resolve_type | `{ context: GraphQL::Query::Context, type: Class, object: Object, path: Array<String, Integer> }`
50
+ # resolve_type_lazy | `{ context: GraphQL::Query::Context, type: Class, object: Object, path: Array<String, Integer> }`
47
51
  #
48
52
  # Note that `execute_field` and `execute_field_lazy` receive different data in different settings:
49
53
  #
@@ -58,8 +62,9 @@ module GraphQL
58
62
  # @param key [String] The name of the event in GraphQL internals
59
63
  # @param metadata [Hash] Event-related metadata (can be anything)
60
64
  # @return [Object] Must return the value of the block
61
- def trace(key, metadata)
62
- call_tracers(0, key, metadata) { yield }
65
+ def trace(key, metadata, &block)
66
+ return yield if @tracers.empty?
67
+ call_tracers(0, key, metadata, &block)
63
68
  end
64
69
 
65
70
  private
@@ -71,39 +76,14 @@ module GraphQL
71
76
  # @param key [String] The current event name
72
77
  # @param metadata [Object] The current event object
73
78
  # @return Whatever the block returns
74
- def call_tracers(idx, key, metadata)
79
+ def call_tracers(idx, key, metadata, &block)
75
80
  if idx == @tracers.length
76
81
  yield
77
82
  else
78
- @tracers[idx].trace(key, metadata) { call_tracers(idx + 1, key, metadata) { yield } }
79
- end
80
- end
81
- end
82
-
83
- class << self
84
- # Install a tracer to receive events.
85
- # @param tracer [<#trace(key, metadata)>]
86
- # @return [void]
87
- # @deprecated See {Schema#tracer} or use `context: { tracers: [...] }`
88
- def install(tracer)
89
- warn("GraphQL::Tracing.install is deprecated, add it to the schema with `tracer(my_tracer)` instead.")
90
- if !tracers.include?(tracer)
91
- @tracers << tracer
83
+ @tracers[idx].trace(key, metadata) { call_tracers(idx + 1, key, metadata, &block) }
92
84
  end
93
85
  end
94
-
95
- # @deprecated See {Schema#tracer} or use `context: { tracers: [...] }`
96
- def uninstall(tracer)
97
- @tracers.delete(tracer)
98
- end
99
-
100
- # @deprecated See {Schema#tracer} or use `context: { tracers: [...] }`
101
- def tracers
102
- @tracers ||= []
103
- end
104
86
  end
105
- # Initialize the array
106
- tracers
107
87
 
108
88
  module NullTracer
109
89
  module_function
@@ -6,7 +6,7 @@ module GraphQL
6
6
  description "Represents non-fractional signed whole numeric values. Since the value may exceed the size of a 32-bit integer, it's encoded as a string."
7
7
 
8
8
  def self.coerce_input(value, _ctx)
9
- Integer(value)
9
+ value && parse_int(value)
10
10
  rescue ArgumentError
11
11
  nil
12
12
  end
@@ -14,6 +14,10 @@ module GraphQL
14
14
  def self.coerce_result(value, _ctx)
15
15
  value.to_i.to_s
16
16
  end
17
+
18
+ def self.parse_int(value)
19
+ value.is_a?(Numeric) ? value : Integer(value, 10)
20
+ end
17
21
  end
18
22
  end
19
23
  end
@@ -9,8 +9,15 @@ module GraphQL
9
9
  MIN = -(2**31)
10
10
  MAX = (2**31) - 1
11
11
 
12
- def self.coerce_input(value, _ctx)
13
- value.is_a?(Numeric) ? value.to_i : nil
12
+ def self.coerce_input(value, ctx)
13
+ return if !value.is_a?(Integer)
14
+
15
+ if value >= MIN && value <= MAX
16
+ value
17
+ else
18
+ err = GraphQL::IntegerDecodingError.new(value)
19
+ ctx.schema.type_error(err, ctx)
20
+ end
14
21
  end
15
22
 
16
23
  def self.coerce_result(value, ctx)
@@ -18,7 +25,7 @@ module GraphQL
18
25
  if value >= MIN && value <= MAX
19
26
  value
20
27
  else
21
- err = GraphQL::IntegerEncodingError.new(value)
28
+ err = GraphQL::IntegerEncodingError.new(value, context: ctx)
22
29
  ctx.schema.type_error(err, ctx)
23
30
  end
24
31
  end
@@ -15,19 +15,27 @@ module GraphQL
15
15
  class ISO8601Date < GraphQL::Schema::Scalar
16
16
  description "An ISO 8601-encoded date"
17
17
 
18
- # @param value [Date]
18
+ # @param value [Date,Time,DateTime,String]
19
19
  # @return [String]
20
20
  def self.coerce_result(value, _ctx)
21
- value.iso8601
21
+ Date.parse(value.to_s).iso8601
22
22
  end
23
23
 
24
- # @param str_value [String]
24
+ # @param str_value [String, Date, DateTime, Time]
25
25
  # @return [Date]
26
- def self.coerce_input(str_value, _ctx)
27
- Date.iso8601(str_value)
28
- rescue ArgumentError
29
- # Invalid input
30
- nil
26
+ def self.coerce_input(value, ctx)
27
+ if value.is_a?(::Date)
28
+ value
29
+ elsif value.is_a?(::DateTime)
30
+ value.to_date
31
+ elsif value.is_a?(::Time)
32
+ value.to_date
33
+ else
34
+ Date.iso8601(value)
35
+ end
36
+ rescue ArgumentError, TypeError
37
+ err = GraphQL::DateEncodingError.new(value)
38
+ ctx.schema.type_error(err, ctx)
31
39
  end
32
40
  end
33
41
  end
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
+
3
+ require 'time'
4
+
2
5
  module GraphQL
3
6
  module Types
4
- # This scalar takes `DateTime`s and transmits them as strings,
7
+ # This scalar takes `Time`s and transmits them as strings,
5
8
  # using ISO 8601 format.
6
9
  #
7
10
  # Use it for fields or arguments as follows:
@@ -29,21 +32,40 @@ module GraphQL
29
32
  @time_precision = value
30
33
  end
31
34
 
32
- # @param value [DateTime]
35
+ # @param value [Time,Date,DateTime,String]
33
36
  # @return [String]
34
37
  def self.coerce_result(value, _ctx)
35
- value.iso8601(time_precision)
36
- rescue ArgumentError
37
- raise GraphQL::Error, "An incompatible object (#{value.class}) was given to #{self}. Make sure that only DateTimes are used with this type."
38
+ case value
39
+ when Date
40
+ return value.to_time.iso8601(time_precision)
41
+ when ::String
42
+ return Time.parse(value).iso8601(time_precision)
43
+ else
44
+ # Time, DateTime or compatible is given:
45
+ return value.iso8601(time_precision)
46
+ end
47
+ rescue StandardError => error
48
+ raise GraphQL::Error, "An incompatible object (#{value.class}) was given to #{self}. Make sure that only Times, Dates, DateTimes, and well-formatted Strings are used with this type. (#{error.message})"
38
49
  end
39
50
 
40
51
  # @param str_value [String]
41
- # @return [DateTime]
52
+ # @return [Time]
42
53
  def self.coerce_input(str_value, _ctx)
43
- DateTime.iso8601(str_value)
44
- rescue ArgumentError
45
- # Invalid input
46
- nil
54
+ Time.iso8601(str_value)
55
+ rescue ArgumentError, TypeError
56
+ begin
57
+ dt = Date.iso8601(str_value).to_time
58
+ # For compatibility, continue accepting dates given without times
59
+ # But without this, it would zero out given any time part of `str_value` (hours and/or minutes)
60
+ if dt.iso8601.start_with?(str_value)
61
+ dt
62
+ else
63
+ nil
64
+ end
65
+ rescue ArgumentError, TypeError
66
+ # Invalid input
67
+ nil
68
+ end
47
69
  end
48
70
  end
49
71
  end
@@ -24,97 +24,15 @@ module GraphQL
24
24
  # end
25
25
  # class Types::PostConnection < Types::BaseConnection
26
26
  # edge_type(Types::PostEdge)
27
+ # edges_nullable(true)
28
+ # edge_nullable(true)
29
+ # node_nullable(true)
30
+ # has_nodes_field(true)
27
31
  # end
28
32
  #
29
33
  # @see Relay::BaseEdge for edge types
30
- class BaseConnection < Types::Relay::BaseObject
31
- extend Forwardable
32
- def_delegators :@object, :cursor_from_node, :parent
33
-
34
- class << self
35
- # @return [Class]
36
- attr_reader :node_type
37
-
38
- # @return [Class]
39
- attr_reader :edge_class
40
-
41
- # Configure this connection to return `edges` and `nodes` based on `edge_type_class`.
42
- #
43
- # This method will use the inputs to create:
44
- # - `edges` field
45
- # - `nodes` field
46
- # - description
47
- #
48
- # It's called when you subclass this base connection, trying to use the
49
- # class name to set defaults. You can call it again in the class definition
50
- # to override the default (or provide a value, if the default lookup failed).
51
- def edge_type(edge_type_class, edge_class: GraphQL::Relay::Edge, node_type: edge_type_class.node_type, nodes_field: true)
52
- # Set this connection's graphql name
53
- node_type_name = node_type.graphql_name
54
-
55
- @node_type = node_type
56
- @edge_type = edge_type_class
57
- @edge_class = edge_class
58
-
59
- field :edges, [edge_type_class, null: true],
60
- null: true,
61
- description: "A list of edges.",
62
- edge_class: edge_class
63
-
64
- define_nodes_field if nodes_field
65
-
66
- description("The connection type for #{node_type_name}.")
67
- end
68
-
69
- # Filter this list according to the way its node type would scope them
70
- def scope_items(items, context)
71
- node_type.scope_items(items, context)
72
- end
73
-
74
- # Add the shortcut `nodes` field to this connection and its subclasses
75
- def nodes_field
76
- define_nodes_field
77
- end
78
-
79
- def authorized?(obj, ctx)
80
- true # Let nodes be filtered out
81
- end
82
-
83
- def accessible?(ctx)
84
- node_type.accessible?(ctx)
85
- end
86
-
87
- def visible?(ctx)
88
- node_type.visible?(ctx)
89
- end
90
-
91
- private
92
-
93
- def define_nodes_field
94
- field :nodes, [@node_type, null: true],
95
- null: true,
96
- description: "A list of nodes."
97
- end
98
- end
99
-
100
- field :page_info, GraphQL::Types::Relay::PageInfo, null: false, description: "Information to aid in pagination."
101
-
102
- # By default this calls through to the ConnectionWrapper's edge nodes method,
103
- # but sometimes you need to override it to support the `nodes` field
104
- def nodes
105
- @object.edge_nodes
106
- end
107
-
108
- def edges
109
- if context.interpreter?
110
- context.schema.after_lazy(object.edge_nodes) do |nodes|
111
- nodes.map { |n| self.class.edge_class.new(n, object) }
112
- end
113
- else
114
- # This is done by edges_instrumentation
115
- @object.edge_nodes
116
- end
117
- end
34
+ class BaseConnection < Schema::Object
35
+ include ConnectionBehaviors
118
36
  end
119
37
  end
120
38
  end
@@ -21,40 +21,8 @@ module GraphQL
21
21
  # end
22
22
  #
23
23
  # @see {Relay::BaseConnection} for connection types
24
- class BaseEdge < Types::Relay::BaseObject
25
- description "An edge in a connection."
26
-
27
- class << self
28
- # Get or set the Object type that this edge wraps.
29
- #
30
- # @param node_type [Class] A `Schema::Object` subclass
31
- # @param null [Boolean]
32
- def node_type(node_type = nil, null: true)
33
- if node_type
34
- @node_type = node_type
35
- # Add a default `node` field
36
- field :node, node_type, null: null, description: "The item at the end of the edge."
37
- end
38
- @node_type
39
- end
40
-
41
- def authorized?(obj, ctx)
42
- true
43
- end
44
-
45
- def accessible?(ctx)
46
- node_type.accessible?(ctx)
47
- end
48
-
49
- def visible?(ctx)
50
- node_type.visible?(ctx)
51
- end
52
- end
53
-
54
-
55
- field :cursor, String,
56
- null: false,
57
- description: "A cursor for use in pagination."
24
+ class BaseEdge < GraphQL::Schema::Object
25
+ include Types::Relay::EdgeBehaviors
58
26
  end
59
27
  end
60
28
  end
@@ -0,0 +1,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Types
5
+ module Relay
6
+ module ConnectionBehaviors
7
+ extend Forwardable
8
+ def_delegators :@object, :cursor_from_node, :parent
9
+
10
+ def self.included(child_class)
11
+ child_class.extend(ClassMethods)
12
+ child_class.extend(Relay::DefaultRelay)
13
+ child_class.default_relay(true)
14
+ child_class.has_nodes_field(true)
15
+ child_class.node_nullable(true)
16
+ child_class.edges_nullable(true)
17
+ child_class.edge_nullable(true)
18
+ add_page_info_field(child_class)
19
+ end
20
+
21
+ module ClassMethods
22
+ # @return [Class]
23
+ attr_reader :node_type
24
+
25
+ # @return [Class]
26
+ attr_reader :edge_class
27
+
28
+ # Configure this connection to return `edges` and `nodes` based on `edge_type_class`.
29
+ #
30
+ # This method will use the inputs to create:
31
+ # - `edges` field
32
+ # - `nodes` field
33
+ # - description
34
+ #
35
+ # It's called when you subclass this base connection, trying to use the
36
+ # class name to set defaults. You can call it again in the class definition
37
+ # to override the default (or provide a value, if the default lookup failed).
38
+ # @param field_options [Hash] Any extra keyword arguments to pass to the `field :edges, ...` and `field :nodes, ...` configurations
39
+ def edge_type(edge_type_class, edge_class: GraphQL::Relay::Edge, node_type: edge_type_class.node_type, nodes_field: self.has_nodes_field, node_nullable: self.node_nullable, edges_nullable: self.edges_nullable, edge_nullable: self.edge_nullable, field_options: nil)
40
+ # Set this connection's graphql name
41
+ node_type_name = node_type.graphql_name
42
+
43
+ @node_type = node_type
44
+ @edge_type = edge_type_class
45
+ @edge_class = edge_class
46
+
47
+ base_field_options = {
48
+ name: :edges,
49
+ type: [edge_type_class, null: edge_nullable],
50
+ null: edges_nullable,
51
+ description: "A list of edges.",
52
+ legacy_edge_class: edge_class, # This is used by the old runtime only, for EdgesInstrumentation
53
+ connection: false,
54
+ }
55
+
56
+ if field_options
57
+ base_field_options.merge!(field_options)
58
+ end
59
+
60
+ field(**base_field_options)
61
+
62
+ define_nodes_field(node_nullable, field_options: field_options) if nodes_field
63
+
64
+ description("The connection type for #{node_type_name}.")
65
+ end
66
+
67
+ # Filter this list according to the way its node type would scope them
68
+ def scope_items(items, context)
69
+ node_type.scope_items(items, context)
70
+ end
71
+
72
+ # Add the shortcut `nodes` field to this connection and its subclasses
73
+ def nodes_field(node_nullable: self.node_nullable, field_options: nil)
74
+ define_nodes_field(node_nullable, field_options: field_options)
75
+ end
76
+
77
+ def authorized?(obj, ctx)
78
+ true # Let nodes be filtered out
79
+ end
80
+
81
+ def accessible?(ctx)
82
+ node_type.accessible?(ctx)
83
+ end
84
+
85
+ def visible?(ctx)
86
+ # if this is an abstract base class, there may be no `node_type`
87
+ node_type ? node_type.visible?(ctx) : super
88
+ end
89
+
90
+ # Set the default `node_nullable` for this class and its child classes. (Defaults to `true`.)
91
+ # Use `node_nullable(false)` in your base class to make non-null `node` and `nodes` fields.
92
+ def node_nullable(new_value = nil)
93
+ if new_value.nil?
94
+ defined?(@node_nullable) ? @node_nullable : superclass.node_nullable
95
+ else
96
+ @node_nullable = new_value
97
+ end
98
+ end
99
+
100
+ # Set the default `edges_nullable` for this class and its child classes. (Defaults to `true`.)
101
+ # Use `edges_nullable(false)` in your base class to make non-null `edges` fields.
102
+ def edges_nullable(new_value = nil)
103
+ if new_value.nil?
104
+ defined?(@edges_nullable) ? @edges_nullable : superclass.edges_nullable
105
+ else
106
+ @edges_nullable = new_value
107
+ end
108
+ end
109
+
110
+ # Set the default `edge_nullable` for this class and its child classes. (Defaults to `true`.)
111
+ # Use `edge_nullable(false)` in your base class to make non-null `edge` fields.
112
+ def edge_nullable(new_value = nil)
113
+ if new_value.nil?
114
+ defined?(@edge_nullable) ? @edge_nullable : superclass.edge_nullable
115
+ else
116
+ @edge_nullable = new_value
117
+ end
118
+ end
119
+
120
+ # Set the default `nodes_field` for this class and its child classes. (Defaults to `true`.)
121
+ # Use `nodes_field(false)` in your base class to prevent adding of a nodes field.
122
+ def has_nodes_field(new_value = nil)
123
+ if new_value.nil?
124
+ defined?(@nodes_field) ? @nodes_field : superclass.has_nodes_field
125
+ else
126
+ @nodes_field = new_value
127
+ end
128
+ end
129
+
130
+ private
131
+
132
+ def define_nodes_field(nullable, field_options: nil)
133
+ base_field_options = {
134
+ name: :nodes,
135
+ type: [@node_type, null: nullable],
136
+ null: nullable,
137
+ description: "A list of nodes.",
138
+ connection: false,
139
+ }
140
+ if field_options
141
+ base_field_options.merge!(field_options)
142
+ end
143
+ field(**base_field_options)
144
+ end
145
+ end
146
+
147
+ class << self
148
+ def add_page_info_field(obj_type)
149
+ obj_type.field :page_info, GraphQL::Types::Relay::PageInfo, null: false, description: "Information to aid in pagination."
150
+ end
151
+ end
152
+
153
+ # By default this calls through to the ConnectionWrapper's edge nodes method,
154
+ # but sometimes you need to override it to support the `nodes` field
155
+ def nodes
156
+ @object.edge_nodes
157
+ end
158
+
159
+ def edges
160
+ if @object.is_a?(GraphQL::Pagination::Connection)
161
+ @object.edges
162
+ elsif context.interpreter?
163
+ context.schema.after_lazy(object.edge_nodes) do |nodes|
164
+ nodes.map { |n| self.class.edge_class.new(n, object) }
165
+ end
166
+ else
167
+ # This is done by edges_instrumentation
168
+ @object.edge_nodes
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Types
5
+ module Relay
6
+ module DefaultRelay
7
+ def self.extended(child_class)
8
+ child_class.default_relay(true)
9
+ end
10
+
11
+ def default_relay(new_value)
12
+ @default_relay = new_value
13
+ end
14
+
15
+ def default_relay?
16
+ !!@default_relay
17
+ end
18
+
19
+ def to_graphql
20
+ type_defn = if method(:to_graphql).super_method.arity
21
+ super(silence_deprecation_warning: true)
22
+ else
23
+ super
24
+ end
25
+ type_defn.default_relay = default_relay?
26
+ type_defn
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Types
5
+ module Relay
6
+ module EdgeBehaviors
7
+ def self.included(child_class)
8
+ child_class.description("An edge in a connection.")
9
+ child_class.field(:cursor, String, null: false, description: "A cursor for use in pagination.")
10
+ child_class.extend(ClassMethods)
11
+ child_class.node_nullable(true)
12
+ end
13
+
14
+ module ClassMethods
15
+ # Get or set the Object type that this edge wraps.
16
+ #
17
+ # @param node_type [Class] A `Schema::Object` subclass
18
+ # @param null [Boolean]
19
+ # @param field_options [Hash] Any extra arguments to pass to the `field :node` configuration
20
+ def node_type(node_type = nil, null: self.node_nullable, field_options: nil)
21
+ if node_type
22
+ @node_type = node_type
23
+ # Add a default `node` field
24
+ base_field_options = {
25
+ name: :node,
26
+ type: node_type,
27
+ null: null,
28
+ description: "The item at the end of the edge.",
29
+ connection: false,
30
+ }
31
+ if field_options
32
+ base_field_options.merge!(field_options)
33
+ end
34
+ field(**base_field_options)
35
+ end
36
+ @node_type
37
+ end
38
+
39
+ def authorized?(obj, ctx)
40
+ true
41
+ end
42
+
43
+ def accessible?(ctx)
44
+ node_type.accessible?(ctx)
45
+ end
46
+
47
+ def visible?(ctx)
48
+ node_type.visible?(ctx)
49
+ end
50
+
51
+ # Set the default `node_nullable` for this class and its child classes. (Defaults to `true`.)
52
+ # Use `node_nullable(false)` in your base class to make non-null `node` field.
53
+ def node_nullable(new_value = nil)
54
+ if new_value.nil?
55
+ defined?(@node_nullable) ? @node_nullable : superclass.node_nullable
56
+ else
57
+ @node_nullable = new_value
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end