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.
- checksums.yaml +4 -4
- data/lib/generators/graphql/core.rb +0 -1
- data/lib/generators/graphql/install_generator.rb +0 -1
- data/lib/generators/graphql/mutation_generator.rb +1 -1
- data/lib/generators/graphql/templates/base_field.erb +4 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +0 -5
- data/lib/generators/graphql/templates/mutation.erb +1 -1
- data/lib/generators/graphql/templates/schema.erb +1 -1
- data/lib/graphql.rb +1 -11
- data/lib/graphql/analysis/ast.rb +2 -2
- data/lib/graphql/analysis/ast/analyzer.rb +4 -23
- data/lib/graphql/analysis/ast/max_query_complexity.rb +3 -3
- data/lib/graphql/analysis/ast/max_query_depth.rb +3 -7
- data/lib/graphql/analysis/ast/query_complexity.rb +2 -2
- data/lib/graphql/argument.rb +6 -2
- data/lib/graphql/backtrace/table.rb +10 -2
- data/lib/graphql/base_type.rb +5 -1
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +5 -9
- data/lib/graphql/define/assign_object_field.rb +2 -2
- data/lib/graphql/define/defined_object_proxy.rb +0 -3
- data/lib/graphql/define/instance_definable.rb +3 -14
- data/lib/graphql/enum_type.rb +4 -0
- data/lib/graphql/execution/directive_checks.rb +2 -2
- data/lib/graphql/execution/errors.rb +14 -15
- data/lib/graphql/execution/execute.rb +1 -1
- data/lib/graphql/execution/interpreter/runtime.rb +17 -39
- data/lib/graphql/execution/multiplex.rb +3 -3
- data/lib/graphql/field.rb +8 -0
- data/lib/graphql/filter.rb +1 -1
- data/lib/graphql/function.rb +1 -1
- data/lib/graphql/input_object_type.rb +1 -2
- data/lib/graphql/introspection/entry_points.rb +1 -2
- data/lib/graphql/introspection/input_value_type.rb +27 -9
- data/lib/graphql/introspection/schema_type.rb +1 -2
- data/lib/graphql/language/block_string.rb +2 -2
- data/lib/graphql/language/document_from_schema_definition.rb +5 -11
- data/lib/graphql/language/lexer.rb +48 -49
- data/lib/graphql/language/lexer.rl +48 -49
- data/lib/graphql/language/nodes.rb +11 -14
- data/lib/graphql/language/parser.rb +645 -650
- data/lib/graphql/language/parser.y +7 -8
- data/lib/graphql/language/token.rb +1 -1
- data/lib/graphql/non_null_type.rb +0 -10
- data/lib/graphql/pagination.rb +6 -0
- data/lib/graphql/pagination/active_record_relation_connection.rb +35 -0
- data/lib/graphql/pagination/array_connection.rb +78 -0
- data/lib/graphql/pagination/connection.rb +150 -0
- data/lib/graphql/pagination/connections.rb +103 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
- data/lib/graphql/pagination/relation_connection.rb +157 -0
- data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
- data/lib/graphql/query.rb +1 -7
- data/lib/graphql/query/arguments.rb +3 -9
- data/lib/graphql/query/context.rb +9 -31
- data/lib/graphql/query/literal_input.rb +29 -10
- data/lib/graphql/query/null_context.rb +0 -4
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query/variables.rb +2 -4
- data/lib/graphql/relay/base_connection.rb +7 -3
- data/lib/graphql/relay/edges_instrumentation.rb +1 -1
- data/lib/graphql/relay/node.rb +2 -2
- data/lib/graphql/relay/relation_connection.rb +5 -9
- data/lib/graphql/schema.rb +27 -68
- data/lib/graphql/schema/argument.rb +31 -5
- data/lib/graphql/schema/base_64_bp.rb +2 -3
- data/lib/graphql/schema/build_from_definition.rb +113 -179
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +10 -4
- data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
- data/lib/graphql/schema/directive.rb +6 -7
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/enum.rb +1 -0
- data/lib/graphql/schema/enum_value.rb +4 -1
- data/lib/graphql/schema/field.rb +37 -39
- data/lib/graphql/schema/field/connection_extension.rb +11 -1
- data/lib/graphql/schema/input_object.rb +2 -5
- data/lib/graphql/schema/interface.rb +2 -0
- data/lib/graphql/schema/introspection_system.rb +1 -4
- data/lib/graphql/schema/loader.rb +6 -12
- data/lib/graphql/schema/member.rb +2 -0
- data/lib/graphql/schema/member/base_dsl_methods.rb +2 -2
- data/lib/graphql/schema/member/build_type.rb +4 -0
- data/lib/graphql/schema/member/cached_graphql_definition.rb +5 -0
- data/lib/graphql/schema/member/has_ast_node.rb +17 -0
- data/lib/graphql/schema/member/has_fields.rb +10 -16
- data/lib/graphql/schema/member/instrumentation.rb +1 -6
- data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
- data/lib/graphql/schema/mutation.rb +1 -1
- data/lib/graphql/schema/object.rb +5 -6
- data/lib/graphql/schema/possible_types.rb +3 -3
- data/lib/graphql/schema/printer.rb +1 -3
- data/lib/graphql/schema/relay_classic_mutation.rb +2 -6
- data/lib/graphql/schema/resolver.rb +5 -35
- data/lib/graphql/schema/scalar.rb +1 -0
- data/lib/graphql/schema/subscription.rb +6 -6
- data/lib/graphql/schema/timeout_middleware.rb +2 -3
- data/lib/graphql/schema/type_expression.rb +27 -17
- data/lib/graphql/schema/union.rb +7 -26
- data/lib/graphql/schema/validation.rb +1 -17
- data/lib/graphql/schema/warden.rb +3 -77
- data/lib/graphql/schema/wrapper.rb +1 -1
- data/lib/graphql/static_validation/definition_dependencies.rb +12 -21
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +9 -4
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +10 -7
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +4 -4
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +3 -3
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +3 -3
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +5 -6
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +1 -1
- data/lib/graphql/subscriptions.rb +7 -7
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +2 -2
- data/lib/graphql/subscriptions/event.rb +5 -19
- data/lib/graphql/subscriptions/instrumentation.rb +9 -4
- data/lib/graphql/subscriptions/subscription_root.rb +2 -10
- data/lib/graphql/tracing/skylight_tracing.rb +0 -1
- data/lib/graphql/types/int.rb +1 -1
- data/lib/graphql/types/relay/base_connection.rb +3 -1
- data/lib/graphql/union_type.rb +23 -58
- data/lib/graphql/upgrader/member.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- metadata +20 -13
- data/lib/generators/graphql/templates/base_mutation.erb +0 -8
- 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 [
|
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
|
-
|
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(
|
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.
|
63
|
-
warn "#{self.graphql_name}'s `field :#{field_defn.
|
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? ||
|
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) }
|
@@ -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,
|
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 =
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
23
|
+
def possible_types(type_defn)
|
24
24
|
case type_defn
|
25
25
|
when Module
|
26
|
-
possible_types(type_defn.graphql_definition
|
26
|
+
possible_types(type_defn.graphql_definition)
|
27
27
|
when GraphQL::UnionType
|
28
|
-
type_defn.possible_types
|
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")
|
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
|
-
|
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(
|
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
|
-
|
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?(
|
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
|
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) && !(
|
139
|
-
|
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
|
@@ -29,7 +29,7 @@ module GraphQL
|
|
29
29
|
# propagate null.
|
30
30
|
null false
|
31
31
|
|
32
|
-
def initialize(object:, context
|
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}",
|
42
|
+
public_send("resolve_#{@mode}", args)
|
43
43
|
end
|
44
44
|
|
45
45
|
# Wrap the user-defined `#subscribe` hook
|
46
|
-
def resolve_subscribe(
|
47
|
-
ret_val = args.any? ? 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(
|
66
|
-
ret_val = args.any? ? 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
|
-
|
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
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
data/lib/graphql/schema/union.rb
CHANGED
@@ -5,19 +5,13 @@ module GraphQL
|
|
5
5
|
extend GraphQL::Schema::Member::AcceptsDefinition
|
6
6
|
|
7
7
|
class << self
|
8
|
-
def possible_types(*types
|
8
|
+
def possible_types(*types)
|
9
9
|
if types.any?
|
10
|
-
|
11
|
-
type_memberships << type_membership_class.new(self, t, **options)
|
12
|
-
end
|
10
|
+
@possible_types = types
|
13
11
|
else
|
14
|
-
|
15
|
-
|
16
|
-
|
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.
|
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.
|
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
|
],
|