graphql 1.9.21 → 1.10.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
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
  ],