graphql 1.9.21 → 1.10.0.pre1

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 (125) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +0 -1
  3. data/lib/generators/graphql/install_generator.rb +0 -1
  4. data/lib/generators/graphql/mutation_generator.rb +1 -1
  5. data/lib/generators/graphql/templates/base_field.erb +4 -0
  6. data/lib/generators/graphql/templates/graphql_controller.erb +0 -5
  7. data/lib/generators/graphql/templates/mutation.erb +1 -1
  8. data/lib/generators/graphql/templates/schema.erb +1 -1
  9. data/lib/graphql.rb +1 -11
  10. data/lib/graphql/analysis/ast.rb +2 -2
  11. data/lib/graphql/analysis/ast/analyzer.rb +4 -23
  12. data/lib/graphql/analysis/ast/max_query_complexity.rb +3 -3
  13. data/lib/graphql/analysis/ast/max_query_depth.rb +3 -7
  14. data/lib/graphql/analysis/ast/query_complexity.rb +2 -2
  15. data/lib/graphql/argument.rb +6 -2
  16. data/lib/graphql/backtrace/table.rb +10 -2
  17. data/lib/graphql/base_type.rb +5 -1
  18. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +5 -9
  19. data/lib/graphql/define/assign_object_field.rb +2 -2
  20. data/lib/graphql/define/defined_object_proxy.rb +0 -3
  21. data/lib/graphql/define/instance_definable.rb +3 -14
  22. data/lib/graphql/enum_type.rb +4 -0
  23. data/lib/graphql/execution/directive_checks.rb +2 -2
  24. data/lib/graphql/execution/errors.rb +14 -15
  25. data/lib/graphql/execution/execute.rb +1 -1
  26. data/lib/graphql/execution/interpreter/runtime.rb +17 -39
  27. data/lib/graphql/execution/multiplex.rb +3 -3
  28. data/lib/graphql/field.rb +8 -0
  29. data/lib/graphql/filter.rb +1 -1
  30. data/lib/graphql/function.rb +1 -1
  31. data/lib/graphql/input_object_type.rb +1 -2
  32. data/lib/graphql/introspection/entry_points.rb +1 -2
  33. data/lib/graphql/introspection/input_value_type.rb +27 -9
  34. data/lib/graphql/introspection/schema_type.rb +1 -2
  35. data/lib/graphql/language/block_string.rb +2 -2
  36. data/lib/graphql/language/document_from_schema_definition.rb +5 -11
  37. data/lib/graphql/language/lexer.rb +48 -49
  38. data/lib/graphql/language/lexer.rl +48 -49
  39. data/lib/graphql/language/nodes.rb +11 -14
  40. data/lib/graphql/language/parser.rb +645 -650
  41. data/lib/graphql/language/parser.y +7 -8
  42. data/lib/graphql/language/token.rb +1 -1
  43. data/lib/graphql/non_null_type.rb +0 -10
  44. data/lib/graphql/pagination.rb +6 -0
  45. data/lib/graphql/pagination/active_record_relation_connection.rb +35 -0
  46. data/lib/graphql/pagination/array_connection.rb +78 -0
  47. data/lib/graphql/pagination/connection.rb +150 -0
  48. data/lib/graphql/pagination/connections.rb +103 -0
  49. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  50. data/lib/graphql/pagination/relation_connection.rb +157 -0
  51. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  52. data/lib/graphql/query.rb +1 -7
  53. data/lib/graphql/query/arguments.rb +3 -9
  54. data/lib/graphql/query/context.rb +9 -31
  55. data/lib/graphql/query/literal_input.rb +29 -10
  56. data/lib/graphql/query/null_context.rb +0 -4
  57. data/lib/graphql/query/variable_validation_error.rb +1 -1
  58. data/lib/graphql/query/variables.rb +2 -4
  59. data/lib/graphql/relay/base_connection.rb +7 -3
  60. data/lib/graphql/relay/edges_instrumentation.rb +1 -1
  61. data/lib/graphql/relay/node.rb +2 -2
  62. data/lib/graphql/relay/relation_connection.rb +5 -9
  63. data/lib/graphql/schema.rb +27 -68
  64. data/lib/graphql/schema/argument.rb +31 -5
  65. data/lib/graphql/schema/base_64_bp.rb +2 -3
  66. data/lib/graphql/schema/build_from_definition.rb +113 -179
  67. data/lib/graphql/schema/build_from_definition/resolve_map.rb +10 -4
  68. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
  69. data/lib/graphql/schema/directive.rb +6 -7
  70. data/lib/graphql/schema/directive/feature.rb +1 -1
  71. data/lib/graphql/schema/enum.rb +1 -0
  72. data/lib/graphql/schema/enum_value.rb +4 -1
  73. data/lib/graphql/schema/field.rb +37 -39
  74. data/lib/graphql/schema/field/connection_extension.rb +11 -1
  75. data/lib/graphql/schema/input_object.rb +2 -5
  76. data/lib/graphql/schema/interface.rb +2 -0
  77. data/lib/graphql/schema/introspection_system.rb +1 -4
  78. data/lib/graphql/schema/loader.rb +6 -12
  79. data/lib/graphql/schema/member.rb +2 -0
  80. data/lib/graphql/schema/member/base_dsl_methods.rb +2 -2
  81. data/lib/graphql/schema/member/build_type.rb +4 -0
  82. data/lib/graphql/schema/member/cached_graphql_definition.rb +5 -0
  83. data/lib/graphql/schema/member/has_ast_node.rb +17 -0
  84. data/lib/graphql/schema/member/has_fields.rb +10 -16
  85. data/lib/graphql/schema/member/instrumentation.rb +1 -6
  86. data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
  87. data/lib/graphql/schema/mutation.rb +1 -1
  88. data/lib/graphql/schema/object.rb +5 -6
  89. data/lib/graphql/schema/possible_types.rb +3 -3
  90. data/lib/graphql/schema/printer.rb +1 -3
  91. data/lib/graphql/schema/relay_classic_mutation.rb +2 -6
  92. data/lib/graphql/schema/resolver.rb +5 -35
  93. data/lib/graphql/schema/scalar.rb +1 -0
  94. data/lib/graphql/schema/subscription.rb +6 -6
  95. data/lib/graphql/schema/timeout_middleware.rb +2 -3
  96. data/lib/graphql/schema/type_expression.rb +27 -17
  97. data/lib/graphql/schema/union.rb +7 -26
  98. data/lib/graphql/schema/validation.rb +1 -17
  99. data/lib/graphql/schema/warden.rb +3 -77
  100. data/lib/graphql/schema/wrapper.rb +1 -1
  101. data/lib/graphql/static_validation/definition_dependencies.rb +12 -21
  102. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +9 -4
  103. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +10 -7
  104. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
  105. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
  106. data/lib/graphql/static_validation/rules/fields_will_merge.rb +4 -4
  107. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +3 -3
  108. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +3 -3
  109. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +5 -6
  110. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  111. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +1 -1
  112. data/lib/graphql/subscriptions.rb +7 -7
  113. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +2 -2
  114. data/lib/graphql/subscriptions/event.rb +5 -19
  115. data/lib/graphql/subscriptions/instrumentation.rb +9 -4
  116. data/lib/graphql/subscriptions/subscription_root.rb +2 -10
  117. data/lib/graphql/tracing/skylight_tracing.rb +0 -1
  118. data/lib/graphql/types/int.rb +1 -1
  119. data/lib/graphql/types/relay/base_connection.rb +3 -1
  120. data/lib/graphql/union_type.rb +23 -58
  121. data/lib/graphql/upgrader/member.rb +1 -1
  122. data/lib/graphql/version.rb +1 -1
  123. metadata +20 -13
  124. data/lib/generators/graphql/templates/base_mutation.erb +0 -8
  125. data/lib/graphql/schema/type_membership.rb +0 -34
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  module GraphQL
4
3
  class Schema
5
4
  class Member
@@ -7,11 +6,11 @@ module GraphQL
7
6
  module HasFields
8
7
  # Add a field to this object or interface with the given definition
9
8
  # @see {GraphQL::Schema::Field#initialize} for method signature
10
- # @return [void]
9
+ # @return [GraphQL::Schema::Field]
11
10
  def field(*args, **kwargs, &block)
12
11
  field_defn = field_class.from_options(*args, owner: self, **kwargs, &block)
13
12
  add_field(field_defn)
14
- nil
13
+ field_defn
15
14
  end
16
15
 
17
16
  # @return [Hash<String => GraphQL::Schema::Field>] Fields on this object, keyed by name, including inherited fields
@@ -39,28 +38,23 @@ module GraphQL
39
38
  end
40
39
  end
41
40
 
42
- # A list of Ruby keywords.
43
- #
44
- # @api private
45
- RUBY_KEYWORDS = [:class, :module, :def, :undef, :begin, :rescue, :ensure, :end, :if, :unless, :then, :elsif, :else, :case, :when, :while, :until, :for, :break, :next, :redo, :retry, :in, :do, :return, :yield, :super, :self, :nil, :true, :false, :and, :or, :not, :alias, :defined?, :BEGIN, :END, :__LINE__, :__FILE__]
46
-
47
- # A list of GraphQL-Ruby keywords.
48
- #
49
- # @api private
50
- GRAPHQL_RUBY_KEYWORDS = [:context, :object, :method]
51
-
52
41
  # A list of field names that we should advise users to pick a different
53
42
  # resolve method name.
54
43
  #
55
44
  # @api private
56
- CONFLICT_FIELD_NAMES = Set.new(GRAPHQL_RUBY_KEYWORDS + RUBY_KEYWORDS)
45
+ CONFLICT_FIELD_NAMES = Set.new([
46
+ # GraphQL-Ruby conflicts
47
+ :context, :object,
48
+ # Ruby built-ins conflicts
49
+ :method, :class
50
+ ])
57
51
 
58
52
  # Register this field with the class, overriding a previous one if needed.
59
53
  # @param field_defn [GraphQL::Schema::Field]
60
54
  # @return [void]
61
55
  def add_field(field_defn)
62
- if CONFLICT_FIELD_NAMES.include?(field_defn.original_name) && field_defn.original_name == field_defn.resolver_method
63
- warn "#{self.graphql_name}'s `field :#{field_defn.original_name}` conflicts with a built-in method, use `resolver_method:` to pick a different resolver method for this field (for example, `resolver_method: :resolve_#{field_defn.original_name}` and `def resolve_#{field_defn.original_name}`)"
56
+ if CONFLICT_FIELD_NAMES.include?(field_defn.resolver_method) && field_defn.original_name == field_defn.resolver_method && field_defn.method_conflict_warning?
57
+ warn "#{self.graphql_name}'s `field :#{field_defn.name}` conflicts with a built-in method, use `resolver_method:` to pick a different resolver method for this field (for example, `resolver_method: :resolve_#{field_defn.resolver_method}` and `def resolve_#{field_defn.resolver_method}`). Or use `method_conflict_warning: false` to suppress this warning."
64
58
  end
65
59
  own_fields[field_defn.name] = field_defn
66
60
  nil
@@ -78,7 +78,7 @@ module GraphQL
78
78
 
79
79
  def call(obj, args, ctx)
80
80
  result = @inner_resolve.call(obj, args, ctx)
81
- if ctx.skip == result || ctx.schema.lazy?(result) || result.nil? || execution_errors?(result) || ctx.wrapped_object
81
+ if ctx.skip == result || ctx.schema.lazy?(result) || result.nil? || result.is_a?(GraphQL::ExecutionError) || ctx.wrapped_object
82
82
  result
83
83
  else
84
84
  ctx.wrapped_object = true
@@ -88,11 +88,6 @@ module GraphQL
88
88
 
89
89
  private
90
90
 
91
- def execution_errors?(result)
92
- result.is_a?(GraphQL::ExecutionError) ||
93
- (result.is_a?(Array) && result.any? && result.all? { |v| v.is_a?(GraphQL::ExecutionError) })
94
- end
95
-
96
91
  def proxy_to_depth(inner_obj, depth, ctx)
97
92
  if depth > 0
98
93
  inner_obj.map { |i| proxy_to_depth(i, depth - 1, ctx) }
@@ -30,7 +30,7 @@ module GraphQL
30
30
 
31
31
  # @return [GraphQL::TypeKinds::TypeKind]
32
32
  def kind
33
- raise GraphQL::RequiredImplementationMissingError
33
+ raise NotImplementedError
34
34
  end
35
35
  end
36
36
  end
@@ -64,7 +64,7 @@ module GraphQL
64
64
 
65
65
  class << self
66
66
  # Override this method to handle legacy-style usages of `MyMutation.field`
67
- def field(*args, **kwargs, &block)
67
+ def field(*args, &block)
68
68
  if args.empty?
69
69
  raise ArgumentError, "#{name}.field is used for adding fields to this mutation. Use `mutation: #{name}` to attach this mutation instead."
70
70
  else
@@ -35,12 +35,10 @@ module GraphQL
35
35
  # @return [GraphQL::Schema::Object, GraphQL::Execution::Lazy]
36
36
  # @raise [GraphQL::UnauthorizedError] if the user-provided hook returns `false`
37
37
  def authorized_new(object, context)
38
- auth_val = context.query.with_error_handling do
39
- begin
40
- authorized?(object, context)
41
- rescue GraphQL::UnauthorizedError => err
42
- context.schema.unauthorized_object(err)
43
- end
38
+ auth_val = begin
39
+ authorized?(object, context)
40
+ rescue GraphQL::UnauthorizedError => err
41
+ context.schema.unauthorized_object(err)
44
42
  end
45
43
 
46
44
  context.schema.after_lazy(auth_val) do |is_authorized|
@@ -120,6 +118,7 @@ module GraphQL
120
118
  obj_type.interfaces = interfaces
121
119
  obj_type.introspection = introspection
122
120
  obj_type.mutation = mutation
121
+ obj_type.ast_node = ast_node
123
122
  fields.each do |field_name, field_inst|
124
123
  field_defn = field_inst.to_graphql
125
124
  obj_type.fields[field_defn.name] = field_defn
@@ -20,12 +20,12 @@ module GraphQL
20
20
  end
21
21
  end
22
22
 
23
- def possible_types(type_defn, ctx)
23
+ def possible_types(type_defn)
24
24
  case type_defn
25
25
  when Module
26
- possible_types(type_defn.graphql_definition, ctx)
26
+ possible_types(type_defn.graphql_definition)
27
27
  when GraphQL::UnionType
28
- type_defn.possible_types(ctx)
28
+ type_defn.possible_types
29
29
  when GraphQL::InterfaceType
30
30
  @interface_implementers[type_defn]
31
31
  when GraphQL::BaseType
@@ -60,9 +60,7 @@ module GraphQL
60
60
 
61
61
  # Return the GraphQL schema string for the introspection type system
62
62
  def self.print_introspection_schema
63
- query_root = ObjectType.define(name: "Root") do
64
- field :throwaway_field, types.String
65
- end
63
+ query_root = ObjectType.define(name: "Root")
66
64
  schema = GraphQL::Schema.define(query: query_root)
67
65
 
68
66
  introspection_schema_ast = GraphQL::Language::DocumentFromSchemaDefinition.new(
@@ -33,13 +33,9 @@ module GraphQL
33
33
  # But when using the interpreter, no instrumenters are applied.
34
34
  if context.interpreter?
35
35
  input = inputs[:input].to_kwargs
36
-
37
- new_extras = field ? field.extras : []
38
- all_extras = self.class.extras + new_extras
39
-
40
36
  # Transfer these from the top-level hash to the
41
37
  # shortcutted `input:` object
42
- all_extras.each do |ext|
38
+ self.class.extras.each do |ext|
43
39
  # It's possible that the `extra` was not passed along by this point,
44
40
  # don't re-add it if it wasn't given here.
45
41
  if inputs.key?(ext)
@@ -61,7 +57,7 @@ module GraphQL
61
57
  end
62
58
 
63
59
  return_value = if input_kwargs.any?
64
- super(**input_kwargs)
60
+ super(input_kwargs)
65
61
  else
66
62
  super()
67
63
  end
@@ -29,11 +29,9 @@ module GraphQL
29
29
 
30
30
  # @param object [Object] the initialize object, pass to {Query.initialize} as `root_value`
31
31
  # @param context [GraphQL::Query::Context]
32
- # @param field [GraphQL::Schema::Field]
33
- def initialize(object:, context:, field:)
32
+ def initialize(object:, context:)
34
33
  @object = object
35
34
  @context = context
36
- @field = field
37
35
  # Since this hash is constantly rebuilt, cache it for this call
38
36
  @arguments_by_keyword = {}
39
37
  self.class.arguments.each do |name, arg|
@@ -48,9 +46,6 @@ module GraphQL
48
46
  # @return [GraphQL::Query::Context]
49
47
  attr_reader :context
50
48
 
51
- # @return [GraphQL::Schema::Field]
52
- attr_reader :field
53
-
54
49
  # This method is _actually_ called by the runtime,
55
50
  # it does some preparation and then eventually calls
56
51
  # the user-defined `#resolve` method.
@@ -76,7 +71,7 @@ module GraphQL
76
71
  context.schema.after_lazy(load_arguments_val) do |loaded_args|
77
72
  # Then call `authorized?`, which may raise or may return a lazy object
78
73
  authorized_val = if loaded_args.any?
79
- authorized?(**loaded_args)
74
+ authorized?(loaded_args)
80
75
  else
81
76
  authorized?
82
77
  end
@@ -108,7 +103,7 @@ module GraphQL
108
103
  # Do the work. Everything happens here.
109
104
  # @return [Object] An object corresponding to the return type
110
105
  def resolve(**args)
111
- raise GraphQL::RequiredImplementationMissingError, "#{self.class.name}#resolve should execute the field's logic"
106
+ raise NotImplementedError, "#{self.class.name}#resolve should execute the field's logic"
112
107
  end
113
108
 
114
109
  # Called before arguments are prepared.
@@ -135,20 +130,8 @@ module GraphQL
135
130
  def authorized?(**inputs)
136
131
  self.class.arguments.each_value do |argument|
137
132
  arg_keyword = argument.keyword
138
- if inputs.key?(arg_keyword) && !(value = inputs[arg_keyword]).nil? && (value != argument.default_value)
139
- loads_type = @arguments_loads_as_type[arg_keyword]
140
- # If this argument resulted in an object being loaded,
141
- # then authorize this loaded object with its own policy.
142
- #
143
- # But if this argument was "just" a plain argument, like
144
- # a boolean, then authorize it based on the mutation.
145
- authorization_value = if loads_type
146
- value
147
- else
148
- self
149
- end
150
-
151
- arg_auth, err = argument.authorized?(authorization_value, context)
133
+ if inputs.key?(arg_keyword) && !(arg_value = inputs[arg_keyword]).nil? && (arg_value != argument.default_value)
134
+ arg_auth, err = argument.authorized?(self, arg_value, context)
152
135
  if !arg_auth
153
136
  return arg_auth, err
154
137
  else
@@ -272,7 +255,6 @@ module GraphQL
272
255
  arguments: arguments,
273
256
  null: null,
274
257
  complexity: complexity,
275
- extensions: extensions,
276
258
  }
277
259
  end
278
260
 
@@ -326,18 +308,6 @@ module GraphQL
326
308
  inherited_lookups.merge(own_arguments_loads_as_type)
327
309
  end
328
310
 
329
- # Registers new extension
330
- # @param extension [Class] Extension class
331
- # @param options [Hash] Optional extension options
332
- def extension(extension, **options)
333
- extensions << {extension => options}
334
- end
335
-
336
- # @api private
337
- def extensions
338
- @extensions ||= []
339
- end
340
-
341
311
  private
342
312
 
343
313
  def own_arguments_loads_as_type
@@ -24,6 +24,7 @@ module GraphQL
24
24
  type_defn.coerce_input = method(:coerce_input)
25
25
  type_defn.metadata[:type_class] = self
26
26
  type_defn.default_scalar = default_scalar
27
+ type_defn.ast_node = ast_node
27
28
  type_defn
28
29
  end
29
30
 
@@ -29,7 +29,7 @@ module GraphQL
29
29
  # propagate null.
30
30
  null false
31
31
 
32
- def initialize(object:, context:, field:)
32
+ def initialize(object:, context:)
33
33
  super
34
34
  # Figure out whether this is an update or an initial subscription
35
35
  @mode = context.query.subscription_update? ? :update : :subscribe
@@ -39,12 +39,12 @@ module GraphQL
39
39
  def resolve(**args)
40
40
  # Dispatch based on `@mode`, which will raise a `NoMethodError` if we ever
41
41
  # have an unexpected `@mode`
42
- public_send("resolve_#{@mode}", **args)
42
+ public_send("resolve_#{@mode}", args)
43
43
  end
44
44
 
45
45
  # Wrap the user-defined `#subscribe` hook
46
- def resolve_subscribe(**args)
47
- ret_val = args.any? ? subscribe(**args) : subscribe
46
+ def resolve_subscribe(args)
47
+ ret_val = args.any? ? subscribe(args) : subscribe
48
48
  if ret_val == :no_response
49
49
  context.skip
50
50
  else
@@ -62,8 +62,8 @@ module GraphQL
62
62
  end
63
63
 
64
64
  # Wrap the user-provided `#update` hook
65
- def resolve_update(**args)
66
- ret_val = args.any? ? update(**args) : update
65
+ def resolve_update(args)
66
+ ret_val = args.any? ? update(args) : update
67
67
  if ret_val == :no_update
68
68
  raise NoUpdateError
69
69
  else
@@ -35,10 +35,9 @@ module GraphQL
35
35
 
36
36
  def call(parent_type, parent_object, field_definition, field_args, query_context)
37
37
  ns = query_context.namespace(self.class)
38
- now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
39
- timeout_at = ns[:timeout_at] ||= now + @max_seconds
38
+ timeout_at = ns[:timeout_at] ||= Time.now + @max_seconds
40
39
 
41
- if timeout_at < now
40
+ if timeout_at < Time.now
42
41
  on_timeout(parent_type, parent_object, field_definition, field_args, query_context)
43
42
  else
44
43
  yield
@@ -9,25 +9,35 @@ module GraphQL
9
9
  # @param ast_node [GraphQL::Language::Nodes::AbstractNode]
10
10
  # @return [GraphQL::BaseType, nil]
11
11
  def self.build_type(types, ast_node)
12
- case ast_node
13
- when GraphQL::Language::Nodes::TypeName
14
- types.fetch(ast_node.name, nil)
15
- when GraphQL::Language::Nodes::NonNullType
16
- ast_inner_type = ast_node.of_type
17
- inner_type = build_type(types, ast_inner_type)
18
- wrap_type(inner_type, GraphQL::NonNullType)
19
- when GraphQL::Language::Nodes::ListType
20
- ast_inner_type = ast_node.of_type
21
- inner_type = build_type(types, ast_inner_type)
22
- wrap_type(inner_type, GraphQL::ListType)
23
- end
12
+ t = type_from_ast(types, ast_node)
13
+ # maybe nil:
14
+ t ? t.graphql_definition : t
24
15
  end
25
16
 
26
- def self.wrap_type(type, wrapper)
27
- if type.nil?
28
- nil
29
- else
30
- wrapper.new(of_type: type)
17
+ class << self
18
+ private
19
+
20
+ def type_from_ast(types, ast_node)
21
+ case ast_node
22
+ when GraphQL::Language::Nodes::TypeName
23
+ types.fetch(ast_node.name, nil)
24
+ when GraphQL::Language::Nodes::NonNullType
25
+ ast_inner_type = ast_node.of_type
26
+ inner_type = build_type(types, ast_inner_type)
27
+ wrap_type(inner_type, GraphQL::Schema::NonNull)
28
+ when GraphQL::Language::Nodes::ListType
29
+ ast_inner_type = ast_node.of_type
30
+ inner_type = build_type(types, ast_inner_type)
31
+ wrap_type(inner_type, GraphQL::Schema::List)
32
+ end
33
+ end
34
+
35
+ def wrap_type(of_type, wrapper)
36
+ if of_type.nil?
37
+ nil
38
+ else
39
+ wrapper.new(of_type)
40
+ end
31
41
  end
32
42
  end
33
43
  end
@@ -5,19 +5,13 @@ module GraphQL
5
5
  extend GraphQL::Schema::Member::AcceptsDefinition
6
6
 
7
7
  class << self
8
- def possible_types(*types, context: GraphQL::Query::NullContext, **options)
8
+ def possible_types(*types)
9
9
  if types.any?
10
- types.each do |t|
11
- type_memberships << type_membership_class.new(self, t, **options)
12
- end
10
+ @possible_types = types
13
11
  else
14
- visible_types = []
15
- type_memberships.each do |type_membership|
16
- if type_membership.visible?(context)
17
- visible_types << type_membership.object_type
18
- end
19
- end
20
- visible_types
12
+ all_possible_types = @possible_types || []
13
+ all_possible_types += super if defined?(super)
14
+ all_possible_types.uniq
21
15
  end
22
16
  end
23
17
 
@@ -25,7 +19,8 @@ module GraphQL
25
19
  type_defn = GraphQL::UnionType.new
26
20
  type_defn.name = graphql_name
27
21
  type_defn.description = description
28
- type_defn.type_memberships = type_memberships
22
+ type_defn.possible_types = possible_types
23
+ type_defn.ast_node = ast_node
29
24
  if respond_to?(:resolve_type)
30
25
  type_defn.resolve_type = method(:resolve_type)
31
26
  end
@@ -33,23 +28,9 @@ module GraphQL
33
28
  type_defn
34
29
  end
35
30
 
36
- def type_membership_class(membership_class = nil)
37
- if membership_class
38
- @type_membership_class = membership_class
39
- else
40
- @type_membership_class || find_inherited_value(:type_membership_class, GraphQL::Schema::TypeMembership)
41
- end
42
- end
43
-
44
31
  def kind
45
32
  GraphQL::TypeKinds::UNION
46
33
  end
47
-
48
- private
49
-
50
- def type_memberships
51
- @type_memberships ||= []
52
- end
53
34
  end
54
35
  end
55
36
  end
@@ -77,18 +77,6 @@ module GraphQL
77
77
  }
78
78
  end
79
79
 
80
- def self.count_at_least(item_name, minimum_count, get_items_proc)
81
- ->(type) {
82
- items = get_items_proc.call(type)
83
-
84
- if items.size < minimum_count
85
- "#{type.name} must define at least #{minimum_count} #{item_name}. #{items.size} defined."
86
- else
87
- nil
88
- end
89
- }
90
- end
91
-
92
80
  def self.assert_named_items_are_valid(item_name, get_items_proc)
93
81
  ->(type) {
94
82
  items = get_items_proc.call(type)
@@ -104,9 +92,7 @@ module GraphQL
104
92
  }
105
93
  end
106
94
 
107
- HAS_AT_LEAST_ONE_FIELD = Rules.count_at_least("field", 1, ->(type) { type.all_fields })
108
95
  FIELDS_ARE_VALID = Rules.assert_named_items_are_valid("field", ->(type) { type.all_fields })
109
- HAS_AT_LEAST_ONE_ARGUMENT = Rules.count_at_least("argument", 1, ->(type) { type.arguments })
110
96
 
111
97
  HAS_ONE_OR_MORE_POSSIBLE_TYPES = ->(type) {
112
98
  type.possible_types.length >= 1 ? nil : "must have at least one possible type"
@@ -135,7 +121,7 @@ module GraphQL
135
121
 
136
122
  TYPE_IS_VALID_INPUT_TYPE = ->(type) {
137
123
  outer_type = type.type
138
- inner_type = outer_type.is_a?(GraphQL::BaseType) ? outer_type.unwrap : nil
124
+ inner_type = outer_type.respond_to?(:unwrap) ? outer_type.unwrap : nil
139
125
 
140
126
  case inner_type
141
127
  when GraphQL::ScalarType, GraphQL::InputObjectType, GraphQL::EnumType
@@ -274,13 +260,11 @@ module GraphQL
274
260
  Rules::DESCRIPTION_IS_STRING_OR_NIL,
275
261
  ],
276
262
  GraphQL::ObjectType => [
277
- Rules::HAS_AT_LEAST_ONE_FIELD,
278
263
  Rules.assert_property_list_of(:interfaces, GraphQL::InterfaceType),
279
264
  Rules::FIELDS_ARE_VALID,
280
265
  Rules::INTERFACES_ARE_IMPLEMENTED,
281
266
  ],
282
267
  GraphQL::InputObjectType => [
283
- Rules::HAS_AT_LEAST_ONE_ARGUMENT,
284
268
  Rules::ARGUMENTS_ARE_STRING_TO_ARGUMENT,
285
269
  Rules::ARGUMENTS_ARE_VALID,
286
270
  ],