graphql 1.10.1 → 1.13.0

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 (292) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +18 -2
  3. data/lib/generators/graphql/install_generator.rb +36 -6
  4. data/lib/generators/graphql/loader_generator.rb +1 -0
  5. data/lib/generators/graphql/mutation_generator.rb +2 -1
  6. data/lib/generators/graphql/object_generator.rb +54 -9
  7. data/lib/generators/graphql/relay.rb +63 -0
  8. data/lib/generators/graphql/relay_generator.rb +21 -0
  9. data/lib/generators/graphql/templates/base_argument.erb +2 -0
  10. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  11. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  12. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  13. data/lib/generators/graphql/templates/base_field.erb +2 -0
  14. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  15. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  16. data/lib/generators/graphql/templates/base_mutation.erb +2 -0
  17. data/lib/generators/graphql/templates/base_object.erb +2 -0
  18. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  19. data/lib/generators/graphql/templates/base_union.erb +2 -0
  20. data/lib/generators/graphql/templates/enum.erb +2 -0
  21. data/lib/generators/graphql/templates/graphql_controller.erb +16 -12
  22. data/lib/generators/graphql/templates/interface.erb +2 -0
  23. data/lib/generators/graphql/templates/loader.erb +2 -0
  24. data/lib/generators/graphql/templates/mutation.erb +2 -0
  25. data/lib/generators/graphql/templates/mutation_type.erb +2 -0
  26. data/lib/generators/graphql/templates/node_type.erb +9 -0
  27. data/lib/generators/graphql/templates/object.erb +3 -1
  28. data/lib/generators/graphql/templates/query_type.erb +3 -3
  29. data/lib/generators/graphql/templates/scalar.erb +2 -0
  30. data/lib/generators/graphql/templates/schema.erb +21 -33
  31. data/lib/generators/graphql/templates/union.erb +3 -1
  32. data/lib/generators/graphql/type_generator.rb +1 -1
  33. data/lib/graphql/analysis/analyze_query.rb +7 -0
  34. data/lib/graphql/analysis/ast/field_usage.rb +24 -1
  35. data/lib/graphql/analysis/ast/query_complexity.rb +126 -109
  36. data/lib/graphql/analysis/ast/visitor.rb +13 -5
  37. data/lib/graphql/analysis/ast.rb +11 -2
  38. data/lib/graphql/argument.rb +3 -3
  39. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  40. data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
  41. data/lib/graphql/backtrace/table.rb +34 -3
  42. data/lib/graphql/backtrace/traced_error.rb +0 -1
  43. data/lib/graphql/backtrace/tracer.rb +40 -9
  44. data/lib/graphql/backtrace.rb +28 -19
  45. data/lib/graphql/backwards_compatibility.rb +2 -1
  46. data/lib/graphql/base_type.rb +1 -1
  47. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +2 -2
  48. data/lib/graphql/compatibility/execution_specification.rb +1 -0
  49. data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
  50. data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
  51. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
  52. data/lib/graphql/dataloader/null_dataloader.rb +22 -0
  53. data/lib/graphql/dataloader/request.rb +19 -0
  54. data/lib/graphql/dataloader/request_all.rb +19 -0
  55. data/lib/graphql/dataloader/source.rb +155 -0
  56. data/lib/graphql/dataloader.rb +308 -0
  57. data/lib/graphql/define/assign_global_id_field.rb +2 -2
  58. data/lib/graphql/define/defined_object_proxy.rb +1 -1
  59. data/lib/graphql/define/instance_definable.rb +34 -4
  60. data/lib/graphql/define/type_definer.rb +5 -5
  61. data/lib/graphql/deprecated_dsl.rb +18 -5
  62. data/lib/graphql/deprecation.rb +9 -0
  63. data/lib/graphql/directive.rb +4 -4
  64. data/lib/graphql/enum_type.rb +7 -1
  65. data/lib/graphql/execution/errors.rb +110 -7
  66. data/lib/graphql/execution/execute.rb +8 -1
  67. data/lib/graphql/execution/instrumentation.rb +1 -1
  68. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  69. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  70. data/lib/graphql/execution/interpreter/arguments_cache.rb +103 -0
  71. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  72. data/lib/graphql/execution/interpreter/resolve.rb +37 -25
  73. data/lib/graphql/execution/interpreter/runtime.rb +685 -421
  74. data/lib/graphql/execution/interpreter.rb +42 -13
  75. data/lib/graphql/execution/lazy.rb +5 -1
  76. data/lib/graphql/execution/lookahead.rb +25 -110
  77. data/lib/graphql/execution/multiplex.rb +37 -25
  78. data/lib/graphql/field.rb +5 -1
  79. data/lib/graphql/function.rb +4 -0
  80. data/lib/graphql/input_object_type.rb +6 -0
  81. data/lib/graphql/integer_decoding_error.rb +17 -0
  82. data/lib/graphql/integer_encoding_error.rb +18 -2
  83. data/lib/graphql/interface_type.rb +7 -0
  84. data/lib/graphql/internal_representation/document.rb +2 -2
  85. data/lib/graphql/internal_representation/rewrite.rb +1 -1
  86. data/lib/graphql/internal_representation/scope.rb +2 -2
  87. data/lib/graphql/internal_representation/visit.rb +2 -2
  88. data/lib/graphql/introspection/directive_type.rb +8 -4
  89. data/lib/graphql/introspection/entry_points.rb +2 -2
  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 +15 -3
  93. data/lib/graphql/introspection/introspection_query.rb +6 -92
  94. data/lib/graphql/introspection/schema_type.rb +4 -4
  95. data/lib/graphql/introspection/type_type.rb +16 -12
  96. data/lib/graphql/introspection.rb +96 -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/document_from_schema_definition.rb +73 -25
  101. data/lib/graphql/language/lexer.rb +4 -3
  102. data/lib/graphql/language/lexer.rl +3 -3
  103. data/lib/graphql/language/nodes.rb +51 -89
  104. data/lib/graphql/language/parser.rb +552 -530
  105. data/lib/graphql/language/parser.y +114 -99
  106. data/lib/graphql/language/printer.rb +7 -2
  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 +2 -2
  110. data/lib/graphql/language.rb +2 -0
  111. data/lib/graphql/name_validator.rb +2 -7
  112. data/lib/graphql/object_type.rb +44 -35
  113. data/lib/graphql/pagination/active_record_relation_connection.rb +14 -1
  114. data/lib/graphql/pagination/array_connection.rb +2 -2
  115. data/lib/graphql/pagination/connection.rb +75 -20
  116. data/lib/graphql/pagination/connections.rb +83 -31
  117. data/lib/graphql/pagination/relation_connection.rb +34 -14
  118. data/lib/graphql/parse_error.rb +0 -1
  119. data/lib/graphql/query/arguments.rb +4 -3
  120. data/lib/graphql/query/arguments_cache.rb +1 -2
  121. data/lib/graphql/query/context.rb +42 -7
  122. data/lib/graphql/query/executor.rb +0 -1
  123. data/lib/graphql/query/fingerprint.rb +26 -0
  124. data/lib/graphql/query/input_validation_result.rb +23 -6
  125. data/lib/graphql/query/literal_input.rb +1 -1
  126. data/lib/graphql/query/null_context.rb +24 -8
  127. data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
  128. data/lib/graphql/query/serial_execution.rb +1 -0
  129. data/lib/graphql/query/validation_pipeline.rb +5 -2
  130. data/lib/graphql/query/variable_validation_error.rb +1 -1
  131. data/lib/graphql/query/variables.rb +14 -4
  132. data/lib/graphql/query.rb +68 -13
  133. data/lib/graphql/railtie.rb +9 -1
  134. data/lib/graphql/rake_task.rb +12 -9
  135. data/lib/graphql/relay/array_connection.rb +10 -12
  136. data/lib/graphql/relay/base_connection.rb +26 -13
  137. data/lib/graphql/relay/connection_instrumentation.rb +4 -4
  138. data/lib/graphql/relay/connection_type.rb +1 -1
  139. data/lib/graphql/relay/edges_instrumentation.rb +0 -1
  140. data/lib/graphql/relay/mutation.rb +1 -0
  141. data/lib/graphql/relay/node.rb +3 -0
  142. data/lib/graphql/relay/range_add.rb +23 -9
  143. data/lib/graphql/relay/relation_connection.rb +8 -10
  144. data/lib/graphql/relay/type_extensions.rb +2 -0
  145. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  146. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  147. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  148. data/lib/graphql/rubocop.rb +4 -0
  149. data/lib/graphql/scalar_type.rb +16 -1
  150. data/lib/graphql/schema/addition.rb +247 -0
  151. data/lib/graphql/schema/argument.rb +210 -12
  152. data/lib/graphql/schema/base_64_encoder.rb +2 -0
  153. data/lib/graphql/schema/build_from_definition/resolve_map.rb +3 -1
  154. data/lib/graphql/schema/build_from_definition.rb +213 -86
  155. data/lib/graphql/schema/default_type_error.rb +2 -0
  156. data/lib/graphql/schema/directive/deprecated.rb +1 -1
  157. data/lib/graphql/schema/directive/feature.rb +1 -1
  158. data/lib/graphql/schema/directive/flagged.rb +57 -0
  159. data/lib/graphql/schema/directive/include.rb +1 -1
  160. data/lib/graphql/schema/directive/skip.rb +1 -1
  161. data/lib/graphql/schema/directive/transform.rb +14 -2
  162. data/lib/graphql/schema/directive.rb +78 -2
  163. data/lib/graphql/schema/enum.rb +80 -9
  164. data/lib/graphql/schema/enum_value.rb +17 -6
  165. data/lib/graphql/schema/field/connection_extension.rb +46 -30
  166. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  167. data/lib/graphql/schema/field.rb +285 -133
  168. data/lib/graphql/schema/find_inherited_value.rb +4 -1
  169. data/lib/graphql/schema/finder.rb +5 -5
  170. data/lib/graphql/schema/input_object.rb +97 -89
  171. data/lib/graphql/schema/interface.rb +24 -19
  172. data/lib/graphql/schema/late_bound_type.rb +2 -2
  173. data/lib/graphql/schema/list.rb +7 -1
  174. data/lib/graphql/schema/loader.rb +137 -103
  175. data/lib/graphql/schema/member/accepts_definition.rb +8 -1
  176. data/lib/graphql/schema/member/base_dsl_methods.rb +15 -19
  177. data/lib/graphql/schema/member/build_type.rb +14 -7
  178. data/lib/graphql/schema/member/has_arguments.rb +205 -12
  179. data/lib/graphql/schema/member/has_ast_node.rb +4 -1
  180. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  181. data/lib/graphql/schema/member/has_directives.rb +98 -0
  182. data/lib/graphql/schema/member/has_fields.rb +95 -30
  183. data/lib/graphql/schema/member/has_interfaces.rb +90 -0
  184. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  185. data/lib/graphql/schema/member/has_validators.rb +31 -0
  186. data/lib/graphql/schema/member/instrumentation.rb +0 -1
  187. data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
  188. data/lib/graphql/schema/member.rb +6 -0
  189. data/lib/graphql/schema/middleware_chain.rb +1 -1
  190. data/lib/graphql/schema/mutation.rb +4 -0
  191. data/lib/graphql/schema/non_null.rb +5 -0
  192. data/lib/graphql/schema/object.rb +47 -46
  193. data/lib/graphql/schema/possible_types.rb +9 -4
  194. data/lib/graphql/schema/printer.rb +16 -34
  195. data/lib/graphql/schema/relay_classic_mutation.rb +32 -4
  196. data/lib/graphql/schema/resolver/has_payload_type.rb +34 -4
  197. data/lib/graphql/schema/resolver.rb +123 -63
  198. data/lib/graphql/schema/scalar.rb +11 -1
  199. data/lib/graphql/schema/subscription.rb +57 -21
  200. data/lib/graphql/schema/timeout.rb +29 -15
  201. data/lib/graphql/schema/timeout_middleware.rb +3 -1
  202. data/lib/graphql/schema/type_expression.rb +1 -1
  203. data/lib/graphql/schema/type_membership.rb +18 -4
  204. data/lib/graphql/schema/union.rb +41 -1
  205. data/lib/graphql/schema/unique_within_type.rb +1 -2
  206. data/lib/graphql/schema/validation.rb +12 -2
  207. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  208. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  209. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  210. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  211. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  212. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  213. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  214. data/lib/graphql/schema/validator/required_validator.rb +68 -0
  215. data/lib/graphql/schema/validator.rb +174 -0
  216. data/lib/graphql/schema/warden.rb +153 -28
  217. data/lib/graphql/schema.rb +364 -330
  218. data/lib/graphql/static_validation/all_rules.rb +1 -0
  219. data/lib/graphql/static_validation/base_visitor.rb +8 -5
  220. data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
  221. data/lib/graphql/static_validation/error.rb +3 -1
  222. data/lib/graphql/static_validation/literal_validator.rb +51 -26
  223. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +44 -87
  224. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +22 -6
  225. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +28 -22
  226. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  227. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
  228. data/lib/graphql/static_validation/rules/fields_will_merge.rb +79 -43
  229. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  230. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  231. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  232. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  233. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -1
  234. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +6 -7
  235. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +9 -10
  236. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +8 -8
  237. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +4 -2
  238. data/lib/graphql/static_validation/validation_context.rb +9 -3
  239. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  240. data/lib/graphql/static_validation/validator.rb +42 -8
  241. data/lib/graphql/static_validation.rb +1 -0
  242. data/lib/graphql/string_encoding_error.rb +13 -3
  243. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +118 -19
  244. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  245. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
  246. data/lib/graphql/subscriptions/event.rb +81 -30
  247. data/lib/graphql/subscriptions/instrumentation.rb +0 -1
  248. data/lib/graphql/subscriptions/serialize.rb +33 -6
  249. data/lib/graphql/subscriptions/subscription_root.rb +15 -4
  250. data/lib/graphql/subscriptions.rb +88 -45
  251. data/lib/graphql/tracing/active_support_notifications_tracing.rb +2 -1
  252. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  253. data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
  254. data/lib/graphql/tracing/new_relic_tracing.rb +1 -12
  255. data/lib/graphql/tracing/platform_tracing.rb +43 -17
  256. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  257. data/lib/graphql/tracing/scout_tracing.rb +11 -0
  258. data/lib/graphql/tracing/skylight_tracing.rb +1 -1
  259. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  260. data/lib/graphql/tracing.rb +9 -33
  261. data/lib/graphql/types/big_int.rb +5 -1
  262. data/lib/graphql/types/int.rb +10 -3
  263. data/lib/graphql/types/iso_8601_date.rb +3 -3
  264. data/lib/graphql/types/iso_8601_date_time.rb +25 -10
  265. data/lib/graphql/types/relay/base_connection.rb +6 -90
  266. data/lib/graphql/types/relay/base_edge.rb +2 -34
  267. data/lib/graphql/types/relay/connection_behaviors.rb +156 -0
  268. data/lib/graphql/types/relay/default_relay.rb +27 -0
  269. data/lib/graphql/types/relay/edge_behaviors.rb +53 -0
  270. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  271. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  272. data/lib/graphql/types/relay/node.rb +2 -4
  273. data/lib/graphql/types/relay/node_behaviors.rb +15 -0
  274. data/lib/graphql/types/relay/node_field.rb +2 -20
  275. data/lib/graphql/types/relay/nodes_field.rb +2 -20
  276. data/lib/graphql/types/relay/page_info.rb +2 -14
  277. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  278. data/lib/graphql/types/relay.rb +11 -3
  279. data/lib/graphql/types/string.rb +8 -2
  280. data/lib/graphql/unauthorized_error.rb +2 -2
  281. data/lib/graphql/union_type.rb +2 -0
  282. data/lib/graphql/upgrader/member.rb +1 -0
  283. data/lib/graphql/upgrader/schema.rb +1 -0
  284. data/lib/graphql/version.rb +1 -1
  285. data/lib/graphql.rb +65 -31
  286. data/readme.md +3 -6
  287. metadata +77 -112
  288. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  289. data/lib/graphql/literal_validation_error.rb +0 -6
  290. data/lib/graphql/types/relay/base_field.rb +0 -22
  291. data/lib/graphql/types/relay/base_interface.rb +0 -29
  292. data/lib/graphql/types/relay/base_object.rb +0 -26
@@ -5,37 +5,49 @@ module GraphQL
5
5
  # to make a schema. This schema is missing some important details like
6
6
  # `resolve` functions, but it does include the full type system,
7
7
  # so you can use it to validate queries.
8
+ #
9
+ # @see GraphQL::Schema.from_introspection for a public API
8
10
  module Loader
9
11
  extend self
10
12
 
11
13
  # Create schema with the result of an introspection query.
12
14
  # @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
13
- # @return [GraphQL::Schema] the schema described by `input`
14
- # @deprecated Use {GraphQL::Schema.from_introspection} instead
15
+ # @return [Class] the schema described by `input`
15
16
  def load(introspection_result)
16
17
  schema = introspection_result.fetch("data").fetch("__schema")
17
18
 
18
19
  types = {}
19
- type_resolver = ->(type) { -> { resolve_type(types, type) } }
20
+ type_resolver = ->(type) { resolve_type(types, type) }
20
21
 
21
22
  schema.fetch("types").each do |type|
22
23
  next if type.fetch("name").start_with?("__")
23
24
  type_object = define_type(type, type_resolver)
24
- types[type_object.name] = type_object
25
+ types[type["name"]] = type_object
25
26
  end
26
27
 
27
- kargs = { orphan_types: types.values, resolve_type: NullResolveType }
28
- [:query, :mutation, :subscription].each do |root|
29
- type = schema["#{root}Type"]
30
- kargs[root] = types.fetch(type.fetch("name")) if type
28
+ directives = []
29
+ schema.fetch("directives", []).each do |directive|
30
+ next if GraphQL::Schema.default_directives.include?(directive.fetch("name"))
31
+ directives << define_directive(directive, type_resolver)
31
32
  end
32
33
 
33
- Schema.define(**kargs, raise_definition_error: true)
34
- end
34
+ Class.new(GraphQL::Schema) do
35
+ orphan_types(types.values)
36
+ directives(directives)
37
+
38
+ def self.resolve_type(*)
39
+ raise(GraphQL::RequiredImplementationMissingError, "This schema was loaded from string, so it can't resolve types for objects")
40
+ end
35
41
 
36
- NullResolveType = ->(type, obj, ctx) {
37
- raise(GraphQL::RequiredImplementationMissingError, "This schema was loaded from string, so it can't resolve types for objects")
38
- }
42
+ [:query, :mutation, :subscription].each do |root|
43
+ type = schema["#{root}Type"]
44
+ if type
45
+ type_defn = types.fetch(type.fetch("name"))
46
+ self.public_send(root, type_defn)
47
+ end
48
+ end
49
+ end
50
+ end
39
51
 
40
52
  NullScalarCoerce = ->(val, _ctx) { val }
41
53
 
@@ -48,14 +60,14 @@ module GraphQL
48
60
  type_name = type.fetch("name")
49
61
  type = types[type_name] || Schema::BUILT_IN_TYPES[type_name]
50
62
  if type.nil?
51
- raise "Type not found: #{type_name.inspect} among #{types.keys.sort}"
63
+ GraphQL::Schema::LateBoundType.new(type_name)
52
64
  else
53
- type.graphql_definition
65
+ type
54
66
  end
55
67
  when "LIST"
56
- ListType.new(of_type: resolve_type(types, type.fetch("ofType")))
68
+ Schema::List.new(resolve_type(types, type.fetch("ofType")))
57
69
  when "NON_NULL"
58
- NonNullType.new(of_type: resolve_type(types, type.fetch("ofType")))
70
+ Schema::NonNull.new(resolve_type(types, type.fetch("ofType")))
59
71
  else
60
72
  fail GraphQL::RequiredImplementationMissingError, "#{kind} not implemented"
61
73
  end
@@ -83,109 +95,131 @@ module GraphQL
83
95
  end
84
96
 
85
97
  def define_type(type, type_resolver)
98
+ loader = self
86
99
  case type.fetch("kind")
87
100
  when "ENUM"
88
- EnumType.define(
89
- name: type["name"],
90
- description: type["description"],
91
- values: type["enumValues"].map { |enum|
92
- EnumType::EnumValue.define(
93
- name: enum["name"],
94
- description: enum["description"],
95
- deprecation_reason: enum["deprecationReason"],
96
- value: enum["name"]
101
+ Class.new(GraphQL::Schema::Enum) do
102
+ graphql_name(type["name"])
103
+ description(type["description"])
104
+ type["enumValues"].each do |enum_value|
105
+ value(
106
+ enum_value["name"],
107
+ description: enum_value["description"],
108
+ deprecation_reason: enum_value["deprecationReason"],
97
109
  )
98
- })
110
+ end
111
+ end
99
112
  when "INTERFACE"
100
- InterfaceType.define(
101
- name: type["name"],
102
- description: type["description"],
103
- fields: Hash[(type["fields"] || []).map { |field|
104
- [field["name"], define_type(field.merge("kind" => "FIELD"), type_resolver)]
105
- }]
106
- )
113
+ Module.new do
114
+ include GraphQL::Schema::Interface
115
+ graphql_name(type["name"])
116
+ description(type["description"])
117
+ loader.build_fields(self, type["fields"] || [], type_resolver)
118
+ end
107
119
  when "INPUT_OBJECT"
108
- InputObjectType.define(
109
- name: type["name"],
110
- description: type["description"],
111
- arguments: Hash[type["inputFields"].map { |arg|
112
- [arg["name"], define_type(arg.merge("kind" => "ARGUMENT"), type_resolver)]
113
- }]
114
- )
115
- when "OBJECT"
116
- ObjectType.define(
117
- name: type["name"],
118
- description: type["description"],
119
- interfaces: (type["interfaces"] || []).map { |interface|
120
- type_resolver.call(interface)
121
- },
122
- fields: Hash[type["fields"].map { |field|
123
- [field["name"], define_type(field.merge("kind" => "FIELD"), type_resolver)]
124
- }]
125
- )
126
- when "FIELD"
127
- defns = {
128
- name: type["name"],
129
- type: type_resolver.call(type["type"]),
130
- description: type["description"],
131
- }
132
-
133
- # Avoid passing an empty hash, which warns on Ruby 2.7
134
- if type["args"].any?
135
- defns[:arguments] = Hash[type["args"].map { |arg|
136
- [arg["name"], define_type(arg.merge("kind" => "ARGUMENT"), type_resolver)]
137
- }]
120
+ Class.new(GraphQL::Schema::InputObject) do
121
+ graphql_name(type["name"])
122
+ description(type["description"])
123
+ loader.build_arguments(self, type["inputFields"], type_resolver)
138
124
  end
139
-
140
- GraphQL::Field.define(**defns)
141
- when "ARGUMENT"
142
- kwargs = {}
143
- if type["defaultValue"]
144
- kwargs[:default_value] = begin
145
- default_value_str = type["defaultValue"]
146
-
147
- dummy_query_str = "query getStuff($var: InputObj = #{default_value_str}) { __typename }"
148
-
149
- # Returns a `GraphQL::Language::Nodes::Document`:
150
- dummy_query_ast = GraphQL.parse(dummy_query_str)
151
-
152
- # Reach into the AST for the default value:
153
- input_value_ast = dummy_query_ast.definitions.first.variables.first.default_value
154
-
155
- extract_default_value(default_value_str, input_value_ast)
125
+ when "OBJECT"
126
+ Class.new(GraphQL::Schema::Object) do
127
+ graphql_name(type["name"])
128
+ description(type["description"])
129
+ if type["interfaces"]
130
+ type["interfaces"].each do |interface_type|
131
+ implements(type_resolver.call(interface_type))
132
+ end
156
133
  end
134
+ loader.build_fields(self, type["fields"], type_resolver)
157
135
  end
158
-
159
- GraphQL::Argument.define(
160
- name: type["name"],
161
- type: type_resolver.call(type["type"]),
162
- description: type["description"],
163
- method_access: false,
164
- **kwargs
165
- )
166
136
  when "SCALAR"
167
137
  type_name = type.fetch("name")
168
- if GraphQL::Schema::BUILT_IN_TYPES[type_name]
169
- GraphQL::Schema::BUILT_IN_TYPES[type_name]
138
+ if (builtin = GraphQL::Schema::BUILT_IN_TYPES[type_name])
139
+ builtin
170
140
  else
171
- ScalarType.define(
172
- name: type["name"],
173
- description: type["description"],
174
- coerce: NullScalarCoerce,
175
- )
141
+ Class.new(GraphQL::Schema::Scalar) do
142
+ graphql_name(type["name"])
143
+ description(type["description"])
144
+ end
176
145
  end
177
146
  when "UNION"
178
- UnionType.define(
179
- name: type["name"],
180
- description: type["description"],
181
- possible_types: type["possibleTypes"].map { |possible_type|
182
- type_resolver.call(possible_type)
183
- }
184
- )
147
+ Class.new(GraphQL::Schema::Union) do
148
+ graphql_name(type["name"])
149
+ description(type["description"])
150
+ possible_types(*(type["possibleTypes"].map { |pt| type_resolver.call(pt) }))
151
+ end
185
152
  else
186
153
  fail GraphQL::RequiredImplementationMissingError, "#{type["kind"]} not implemented"
187
154
  end
188
155
  end
156
+
157
+ def define_directive(directive, type_resolver)
158
+ loader = self
159
+ Class.new(GraphQL::Schema::Directive) do
160
+ graphql_name(directive["name"])
161
+ description(directive["description"])
162
+ locations(*directive["locations"].map(&:to_sym))
163
+ loader.build_arguments(self, directive["args"], type_resolver)
164
+ end
165
+ end
166
+
167
+ public
168
+
169
+ def build_fields(type_defn, fields, type_resolver)
170
+ loader = self
171
+ fields.each do |field_hash|
172
+ unwrapped_field_hash = field_hash
173
+ while (of_type = unwrapped_field_hash["ofType"])
174
+ unwrapped_field_hash = of_type
175
+ end
176
+ type_name = unwrapped_field_hash["name"]
177
+
178
+ type_defn.field(
179
+ field_hash["name"],
180
+ type: type_resolver.call(field_hash["type"]),
181
+ description: field_hash["description"],
182
+ deprecation_reason: field_hash["deprecationReason"],
183
+ null: true,
184
+ camelize: false,
185
+ connection_extension: nil,
186
+ connection: type_name.end_with?("Connection"),
187
+ ) do
188
+ if field_hash["args"].any?
189
+ loader.build_arguments(self, field_hash["args"], type_resolver)
190
+ end
191
+ end
192
+ end
193
+ end
194
+
195
+ def build_arguments(arg_owner, args, type_resolver)
196
+ args.each do |arg|
197
+ kwargs = {
198
+ type: type_resolver.call(arg["type"]),
199
+ description: arg["description"],
200
+ deprecation_reason: arg["deprecationReason"],
201
+ required: false,
202
+ method_access: false,
203
+ camelize: false,
204
+ }
205
+
206
+ if arg["defaultValue"]
207
+ default_value_str = arg["defaultValue"]
208
+
209
+ dummy_query_str = "query getStuff($var: InputObj = #{default_value_str}) { __typename }"
210
+
211
+ # Returns a `GraphQL::Language::Nodes::Document`:
212
+ dummy_query_ast = GraphQL.parse(dummy_query_str)
213
+
214
+ # Reach into the AST for the default value:
215
+ input_value_ast = dummy_query_ast.definitions.first.variables.first.default_value
216
+
217
+ kwargs[:default_value] = extract_default_value(default_value_str, input_value_ast)
218
+ end
219
+
220
+ arg_owner.argument(arg["name"], **kwargs)
221
+ end
222
+ end
189
223
  end
190
224
  end
191
225
  end
@@ -85,8 +85,15 @@ module GraphQL
85
85
  define_method(name) do |*args|
86
86
  if args.any?
87
87
  instance_variable_set(ivar_name, args)
88
+ else
89
+ if (v = instance_variable_get(ivar_name))
90
+ v
91
+ elsif (ancestor = ancestors.find { |i| i.respond_to?(name) && i != self })
92
+ ancestor.public_send(name)
93
+ else
94
+ nil
95
+ end
88
96
  end
89
- instance_variable_get(ivar_name) || ((int = interfaces.first { |i| i.respond_to?()}) && int.public_send(name))
90
97
  end
91
98
  end
92
99
  end
@@ -19,6 +19,7 @@ module GraphQL
19
19
  # @return [String]
20
20
  def graphql_name(new_name = nil)
21
21
  if new_name
22
+ GraphQL::NameValidator.validate!(new_name)
22
23
  @graphql_name = new_name
23
24
  else
24
25
  overridden_graphql_name || default_graphql_name
@@ -26,7 +27,7 @@ module GraphQL
26
27
  end
27
28
 
28
29
  def overridden_graphql_name
29
- @graphql_name
30
+ defined?(@graphql_name) ? @graphql_name : nil
30
31
  end
31
32
 
32
33
  # Just a convenience method to point out that people should use graphql_name instead
@@ -46,8 +47,10 @@ module GraphQL
46
47
  def description(new_description = nil)
47
48
  if new_description
48
49
  @description = new_description
49
- else
50
+ elsif defined?(@description)
50
51
  @description
52
+ else
53
+ nil
51
54
  end
52
55
  end
53
56
 
@@ -68,8 +71,10 @@ module GraphQL
68
71
  def introspection(new_introspection = nil)
69
72
  if !new_introspection.nil?
70
73
  @introspection = new_introspection
71
- else
74
+ elsif defined?(@introspection)
72
75
  @introspection
76
+ else
77
+ false
73
78
  end
74
79
  end
75
80
 
@@ -82,8 +87,11 @@ module GraphQL
82
87
  def mutation(mutation_class = nil)
83
88
  if mutation_class
84
89
  @mutation = mutation_class
90
+ elsif defined?(@mutation)
91
+ @mutation
92
+ else
93
+ nil
85
94
  end
86
- @mutation
87
95
  end
88
96
 
89
97
  # @return [GraphQL::BaseType] Convert this type to a legacy-style object.
@@ -105,27 +113,15 @@ module GraphQL
105
113
  end
106
114
 
107
115
  def visible?(context)
108
- if @mutation
109
- @mutation.visible?(context)
110
- else
111
- true
112
- end
116
+ true
113
117
  end
114
118
 
115
119
  def accessible?(context)
116
- if @mutation
117
- @mutation.accessible?(context)
118
- else
119
- true
120
- end
120
+ true
121
121
  end
122
122
 
123
123
  def authorized?(object, context)
124
- if @mutation
125
- @mutation.authorized?(object, context)
126
- else
127
- true
128
- end
124
+ true
129
125
  end
130
126
  end
131
127
  end
@@ -56,11 +56,11 @@ module GraphQL
56
56
  parse_type(type_expr.first, null: false)
57
57
  when 2
58
58
  inner_type, nullable_option = type_expr
59
- if nullable_option.keys != [:null] || nullable_option.values != [true]
59
+ if nullable_option.keys != [:null] || (nullable_option[:null] != true && nullable_option[:null] != false)
60
60
  raise ArgumentError, LIST_TYPE_ERROR
61
61
  end
62
62
  list_type = true
63
- parse_type(inner_type, null: true)
63
+ parse_type(inner_type, null: nullable_option[:null])
64
64
  else
65
65
  raise ArgumentError, LIST_TYPE_ERROR
66
66
  end
@@ -71,7 +71,7 @@ module GraphQL
71
71
  if type_expr.respond_to?(:graphql_definition)
72
72
  type_expr
73
73
  else
74
- # Eg `String` => GraphQL::STRING_TYPE
74
+ # Eg `String` => GraphQL::Types::String
75
75
  parse_type(type_expr.name, null: true)
76
76
  end
77
77
  when Proc
@@ -120,6 +120,7 @@ module GraphQL
120
120
  end
121
121
 
122
122
  def camelize(string)
123
+ return string if string == '_'
123
124
  return string unless string.include?("_")
124
125
  camelized = string.split('_').map(&:capitalize).join
125
126
  camelized[0] = camelized[0].downcase
@@ -162,10 +163,16 @@ module GraphQL
162
163
  end
163
164
 
164
165
  def underscore(string)
165
- string
166
- .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') # URLDecoder -> URL_Decoder
167
- .gsub(/([a-z\d])([A-Z])/,'\1_\2') # someThing -> some_Thing
168
- .downcase
166
+ if string.match?(/\A[a-z_]+\Z/)
167
+ return string
168
+ end
169
+ string2 = string.dup
170
+
171
+ string2.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2') # URLDecoder -> URL_Decoder
172
+ string2.gsub!(/([a-z\d])([A-Z])/,'\1_\2') # someThing -> some_Thing
173
+ string2.downcase!
174
+
175
+ string2
169
176
  end
170
177
  end
171
178
  end