graphql 1.12.24 → 1.13.19
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.
- checksums.yaml +4 -4
- data/lib/generators/graphql/core.rb +3 -8
- data/lib/generators/graphql/enum_generator.rb +4 -10
- data/lib/generators/graphql/field_extractor.rb +31 -0
- data/lib/generators/graphql/input_generator.rb +50 -0
- data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
- data/lib/generators/graphql/install_generator.rb +10 -3
- data/lib/generators/graphql/interface_generator.rb +7 -7
- data/lib/generators/graphql/mutation_create_generator.rb +22 -0
- data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
- data/lib/generators/graphql/mutation_generator.rb +5 -30
- data/lib/generators/graphql/mutation_update_generator.rb +22 -0
- data/lib/generators/graphql/object_generator.rb +8 -37
- data/lib/generators/graphql/orm_mutations_base.rb +40 -0
- data/lib/generators/graphql/scalar_generator.rb +4 -2
- data/lib/generators/graphql/templates/enum.erb +5 -1
- data/lib/generators/graphql/templates/input.erb +9 -0
- data/lib/generators/graphql/templates/interface.erb +4 -2
- data/lib/generators/graphql/templates/mutation.erb +1 -1
- data/lib/generators/graphql/templates/mutation_create.erb +20 -0
- data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
- data/lib/generators/graphql/templates/mutation_update.erb +21 -0
- data/lib/generators/graphql/templates/object.erb +4 -2
- data/lib/generators/graphql/templates/scalar.erb +3 -1
- data/lib/generators/graphql/templates/union.erb +4 -2
- data/lib/generators/graphql/type_generator.rb +46 -10
- data/lib/generators/graphql/union_generator.rb +5 -5
- data/lib/graphql/analysis/ast/field_usage.rb +2 -2
- data/lib/graphql/analysis/ast/query_complexity.rb +10 -14
- data/lib/graphql/analysis/ast/visitor.rb +5 -4
- data/lib/graphql/argument.rb +1 -1
- data/lib/graphql/backtrace/table.rb +1 -1
- data/lib/graphql/base_type.rb +5 -3
- data/lib/graphql/boolean_type.rb +1 -1
- data/lib/graphql/dataloader/source.rb +2 -2
- data/lib/graphql/dataloader.rb +55 -22
- data/lib/graphql/date_encoding_error.rb +16 -0
- data/lib/graphql/define/instance_definable.rb +15 -0
- data/lib/graphql/directive/deprecated_directive.rb +1 -1
- data/lib/graphql/directive/include_directive.rb +1 -1
- data/lib/graphql/directive/skip_directive.rb +1 -1
- data/lib/graphql/directive.rb +1 -5
- data/lib/graphql/enum_type.rb +7 -3
- data/lib/graphql/execution/errors.rb +1 -0
- data/lib/graphql/execution/interpreter/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +6 -4
- data/lib/graphql/execution/interpreter/runtime.rb +66 -38
- data/lib/graphql/execution/lookahead.rb +2 -2
- data/lib/graphql/execution/multiplex.rb +4 -1
- data/lib/graphql/field.rb +1 -1
- data/lib/graphql/float_type.rb +1 -1
- data/lib/graphql/id_type.rb +1 -1
- data/lib/graphql/input_object_type.rb +1 -1
- data/lib/graphql/int_type.rb +1 -1
- data/lib/graphql/interface_type.rb +1 -1
- data/lib/graphql/introspection/directive_location_enum.rb +2 -2
- data/lib/graphql/introspection/directive_type.rb +5 -3
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/introspection/enum_value_type.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +3 -3
- data/lib/graphql/introspection/input_value_type.rb +4 -4
- data/lib/graphql/introspection/schema_type.rb +9 -4
- data/lib/graphql/introspection/type_type.rb +18 -12
- data/lib/graphql/introspection.rb +4 -1
- data/lib/graphql/language/block_string.rb +2 -6
- data/lib/graphql/language/document_from_schema_definition.rb +11 -4
- data/lib/graphql/language/lexer.rb +50 -28
- data/lib/graphql/language/lexer.rl +2 -4
- data/lib/graphql/language/nodes.rb +4 -3
- data/lib/graphql/language/parser.rb +841 -820
- data/lib/graphql/language/parser.y +13 -6
- data/lib/graphql/language/printer.rb +10 -1
- data/lib/graphql/language/sanitized_printer.rb +5 -5
- data/lib/graphql/language/token.rb +0 -4
- data/lib/graphql/name_validator.rb +0 -4
- data/lib/graphql/object_type.rb +2 -2
- data/lib/graphql/pagination/active_record_relation_connection.rb +43 -6
- data/lib/graphql/pagination/relation_connection.rb +59 -29
- data/lib/graphql/query/arguments.rb +1 -1
- data/lib/graphql/query/arguments_cache.rb +1 -1
- data/lib/graphql/query/context.rb +15 -2
- data/lib/graphql/query/input_validation_result.rb +9 -0
- data/lib/graphql/query/literal_input.rb +1 -1
- data/lib/graphql/query/null_context.rb +12 -7
- data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
- data/lib/graphql/query/validation_pipeline.rb +2 -3
- data/lib/graphql/query/variable_validation_error.rb +2 -2
- data/lib/graphql/query/variables.rb +35 -4
- data/lib/graphql/query.rb +0 -1
- data/lib/graphql/relay/connection_type.rb +15 -2
- data/lib/graphql/relay/edges_instrumentation.rb +0 -1
- data/lib/graphql/relay/global_id_resolve.rb +1 -2
- data/lib/graphql/relay/mutation.rb +1 -1
- data/lib/graphql/relay/page_info.rb +1 -1
- data/lib/graphql/relay/range_add.rb +4 -0
- data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
- data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
- data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
- data/lib/graphql/rubocop.rb +4 -0
- data/lib/graphql/scalar_type.rb +1 -1
- data/lib/graphql/schema/addition.rb +37 -28
- data/lib/graphql/schema/argument.rb +30 -15
- data/lib/graphql/schema/build_from_definition.rb +6 -5
- data/lib/graphql/schema/directive/feature.rb +1 -1
- data/lib/graphql/schema/directive/flagged.rb +2 -2
- data/lib/graphql/schema/directive/include.rb +1 -1
- data/lib/graphql/schema/directive/skip.rb +1 -1
- data/lib/graphql/schema/directive/transform.rb +1 -1
- data/lib/graphql/schema/directive.rb +23 -4
- data/lib/graphql/schema/enum.rb +61 -12
- data/lib/graphql/schema/enum_value.rb +6 -0
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +261 -83
- data/lib/graphql/schema/field_extension.rb +89 -2
- data/lib/graphql/schema/find_inherited_value.rb +1 -0
- data/lib/graphql/schema/finder.rb +5 -5
- data/lib/graphql/schema/input_object.rb +24 -7
- data/lib/graphql/schema/interface.rb +11 -20
- data/lib/graphql/schema/introspection_system.rb +1 -1
- data/lib/graphql/schema/list.rb +21 -4
- data/lib/graphql/schema/loader.rb +3 -0
- data/lib/graphql/schema/member/accepts_definition.rb +15 -3
- data/lib/graphql/schema/member/base_dsl_methods.rb +1 -1
- data/lib/graphql/schema/member/build_type.rb +0 -4
- data/lib/graphql/schema/member/cached_graphql_definition.rb +29 -2
- data/lib/graphql/schema/member/has_arguments.rb +56 -14
- data/lib/graphql/schema/member/has_deprecation_reason.rb +1 -1
- data/lib/graphql/schema/member/has_fields.rb +76 -18
- data/lib/graphql/schema/member/has_interfaces.rb +100 -0
- data/lib/graphql/schema/member/validates_input.rb +2 -2
- data/lib/graphql/schema/member.rb +1 -0
- data/lib/graphql/schema/non_null.rb +9 -3
- data/lib/graphql/schema/object.rb +10 -75
- data/lib/graphql/schema/printer.rb +1 -1
- data/lib/graphql/schema/relay_classic_mutation.rb +37 -3
- data/lib/graphql/schema/resolver/has_payload_type.rb +27 -2
- data/lib/graphql/schema/resolver.rb +37 -17
- data/lib/graphql/schema/scalar.rb +15 -1
- data/lib/graphql/schema/subscription.rb +11 -1
- data/lib/graphql/schema/traversal.rb +1 -1
- data/lib/graphql/schema/type_expression.rb +1 -1
- data/lib/graphql/schema/type_membership.rb +18 -4
- data/lib/graphql/schema/union.rb +8 -1
- data/lib/graphql/schema/validator/format_validator.rb +0 -4
- data/lib/graphql/schema/validator/numericality_validator.rb +1 -0
- data/lib/graphql/schema/validator/required_validator.rb +29 -15
- data/lib/graphql/schema/validator.rb +4 -7
- data/lib/graphql/schema/warden.rb +126 -53
- data/lib/graphql/schema.rb +120 -24
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/base_visitor.rb +6 -6
- data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
- data/lib/graphql/static_validation/literal_validator.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +1 -1
- data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
- data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +3 -3
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +4 -4
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +13 -7
- data/lib/graphql/static_validation/validation_context.rb +4 -0
- data/lib/graphql/string_type.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +8 -4
- data/lib/graphql/subscriptions/event.rb +20 -12
- data/lib/graphql/subscriptions/serialize.rb +22 -2
- data/lib/graphql/subscriptions.rb +17 -19
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +6 -20
- data/lib/graphql/tracing/data_dog_tracing.rb +24 -2
- data/lib/graphql/tracing/notifications_tracing.rb +59 -0
- data/lib/graphql/tracing/platform_tracing.rb +20 -10
- data/lib/graphql/types/iso_8601_date.rb +13 -5
- data/lib/graphql/types/iso_8601_date_time.rb +8 -1
- data/lib/graphql/types/relay/connection_behaviors.rb +28 -10
- data/lib/graphql/types/relay/default_relay.rb +5 -1
- data/lib/graphql/types/relay/edge_behaviors.rb +13 -2
- data/lib/graphql/types/relay/has_node_field.rb +1 -1
- data/lib/graphql/types/relay/has_nodes_field.rb +1 -1
- data/lib/graphql/types/relay/node_field.rb +2 -3
- data/lib/graphql/types/relay/nodes_field.rb +19 -3
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/union_type.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +22 -32
- metadata +31 -11
- /data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +0 -0
- /data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +0 -0
data/lib/graphql/query.rb
CHANGED
@@ -5,9 +5,22 @@ module GraphQL
|
|
5
5
|
module ConnectionType
|
6
6
|
class << self
|
7
7
|
# @return [Boolean] If true, connection types get a `nodes` shortcut field
|
8
|
-
|
8
|
+
def default_nodes_field=(new_setting)
|
9
|
+
if new_setting
|
10
|
+
warn("GraphQL::Relay::ConnectionType will be removed in GraphQL 2.0.0; migrate to `GraphQL::Pagination::Connections` and remove this setting (`default_nodes_field = true`).")
|
11
|
+
end
|
12
|
+
@default_nodes_field = new_setting
|
13
|
+
end
|
14
|
+
attr_reader :default_nodes_field
|
15
|
+
|
9
16
|
# @return [Boolean] If true, connections check for reverse-direction `has*Page` values
|
10
|
-
|
17
|
+
def bidirectional_pagination=(new_setting)
|
18
|
+
if new_setting
|
19
|
+
warn("GraphQL::Relay::ConnectionType will be removed in GraphQL 2.0.0; migrate to `GraphQL::Pagination::Connections` and remove this setting (`bidirectional_pagination = true`).")
|
20
|
+
end
|
21
|
+
@bidirectional_pagination = new_setting
|
22
|
+
end
|
23
|
+
attr_reader :bidirectional_pagination
|
11
24
|
end
|
12
25
|
|
13
26
|
self.default_nodes_field = false
|
@@ -10,8 +10,7 @@ module GraphQL
|
|
10
10
|
if obj.is_a?(GraphQL::Schema::Object)
|
11
11
|
obj = obj.object
|
12
12
|
end
|
13
|
-
|
14
|
-
ctx.query.schema.id_from_object(obj, type, ctx)
|
13
|
+
ctx.query.schema.id_from_object(obj, @type, ctx)
|
15
14
|
end
|
16
15
|
end
|
17
16
|
end
|
@@ -35,6 +35,10 @@ module GraphQL
|
|
35
35
|
# @param context [GraphQL::Query::Context] The surrounding `ctx`, will be passed to the connection if provided (this is required for cursor encoders)
|
36
36
|
# @param edge_class [Class] The class to wrap `item` with (defaults to the connection's edge class)
|
37
37
|
def initialize(collection:, item:, parent: nil, context: nil, edge_class: nil)
|
38
|
+
if context.nil?
|
39
|
+
caller_loc = caller(2, 1).first
|
40
|
+
GraphQL::Deprecation.warn("`context: ...` will be required by `RangeAdd.new` in GraphQL-Ruby 2.0. Add `context: context` to the call at #{caller_loc}.")
|
41
|
+
end
|
38
42
|
if context && context.schema.new_connections?
|
39
43
|
conn_class = context.schema.connections.wrapper_for(collection)
|
40
44
|
# The rest will be added by ConnectionExtension
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "rubocop"
|
3
|
+
|
4
|
+
module GraphQL
|
5
|
+
module Rubocop
|
6
|
+
module GraphQL
|
7
|
+
class BaseCop < RuboCop::Cop::Base
|
8
|
+
extend RuboCop::Cop::AutoCorrector
|
9
|
+
|
10
|
+
# Return the source of `send_node`, but without the keyword argument represented by `pair_node`
|
11
|
+
def source_without_keyword_argument(send_node, pair_node)
|
12
|
+
# work back to the preceeding comma
|
13
|
+
first_pos = pair_node.location.expression.begin_pos
|
14
|
+
end_pos = pair_node.location.expression.end_pos
|
15
|
+
node_source = send_node.source_range.source
|
16
|
+
node_first_pos = send_node.location.expression.begin_pos
|
17
|
+
|
18
|
+
relative_first_pos = first_pos - node_first_pos
|
19
|
+
relative_last_pos = end_pos - node_first_pos
|
20
|
+
|
21
|
+
begin_removal_pos = relative_first_pos
|
22
|
+
while node_source[begin_removal_pos] != ","
|
23
|
+
begin_removal_pos -= 1
|
24
|
+
if begin_removal_pos < 1
|
25
|
+
raise "Invariant: somehow backtracked to beginning of node looking for a comma (node source: #{node_source.inspect})"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end_removal_pos = relative_last_pos
|
30
|
+
cleaned_node_source = node_source[0...begin_removal_pos] + node_source[end_removal_pos..-1]
|
31
|
+
cleaned_node_source
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative "base_cop"
|
3
|
+
|
4
|
+
module GraphQL
|
5
|
+
module Rubocop
|
6
|
+
module GraphQL
|
7
|
+
# Identify (and auto-correct) any field configuration which duplicates
|
8
|
+
# the default `null: true` property.
|
9
|
+
#
|
10
|
+
# `null: true` is default because nullable fields can always be converted
|
11
|
+
# to non-null fields (`null: false`) without a breaking change. (The opposite change, from `null: false`
|
12
|
+
# to `null: true`, change.)
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# # Both of these define `name: String` in GraphQL:
|
16
|
+
#
|
17
|
+
# # bad
|
18
|
+
# field :name, String, null: true
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# field :name, String
|
22
|
+
#
|
23
|
+
class DefaultNullTrue < BaseCop
|
24
|
+
MSG = "`null: true` is the default and can be removed."
|
25
|
+
|
26
|
+
def_node_matcher :field_config_with_null_true?, <<-Pattern
|
27
|
+
(
|
28
|
+
send nil? :field ... (hash $(pair (sym :null) (true)) ...)
|
29
|
+
)
|
30
|
+
Pattern
|
31
|
+
|
32
|
+
def on_send(node)
|
33
|
+
field_config_with_null_true?(node) do |null_config|
|
34
|
+
add_offense(null_config) do |corrector|
|
35
|
+
cleaned_node_source = source_without_keyword_argument(node, null_config)
|
36
|
+
corrector.replace(node.source_range, cleaned_node_source)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative "./base_cop"
|
3
|
+
|
4
|
+
module GraphQL
|
5
|
+
module Rubocop
|
6
|
+
module GraphQL
|
7
|
+
# Identify (and auto-correct) any argument configuration which duplicates
|
8
|
+
# the default `required: true` property.
|
9
|
+
#
|
10
|
+
# `required: true` is default because required arguments can always be converted
|
11
|
+
# to optional arguments (`required: false`) without a breaking change. (The opposite change, from `required: false`
|
12
|
+
# to `required: true`, change.)
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# # Both of these define `id: ID!` in GraphQL:
|
16
|
+
#
|
17
|
+
# # bad
|
18
|
+
# argument :id, ID, required: true
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# argument :id, ID
|
22
|
+
#
|
23
|
+
class DefaultRequiredTrue < BaseCop
|
24
|
+
MSG = "`required: true` is the default and can be removed."
|
25
|
+
|
26
|
+
def_node_matcher :argument_config_with_required_true?, <<-Pattern
|
27
|
+
(
|
28
|
+
send {nil? _} :argument ... (hash <$(pair (sym :required) (true)) ...>)
|
29
|
+
)
|
30
|
+
Pattern
|
31
|
+
|
32
|
+
def on_send(node)
|
33
|
+
argument_config_with_required_true?(node) do |required_config|
|
34
|
+
add_offense(required_config) do |corrector|
|
35
|
+
cleaned_node_source = source_without_keyword_argument(node, required_config)
|
36
|
+
corrector.replace(node, cleaned_node_source)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/graphql/scalar_type.rb
CHANGED
@@ -4,7 +4,7 @@ module GraphQL
|
|
4
4
|
class ScalarType < GraphQL::BaseType
|
5
5
|
extend Define::InstanceDefinable::DeprecatedDefine
|
6
6
|
|
7
|
-
|
7
|
+
deprecated_accepts_definitions :coerce, :coerce_input, :coerce_result
|
8
8
|
ensure_defined :coerce_non_null_input, :coerce_result
|
9
9
|
|
10
10
|
module NoOpCoerce
|
@@ -24,7 +24,13 @@ module GraphQL
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def get_type(name)
|
27
|
-
@types[name]
|
27
|
+
local_type = @types[name]
|
28
|
+
# This isn't really sophisticated, but
|
29
|
+
# I think it's good enough to support the current usage of LateBoundTypes
|
30
|
+
if local_type.is_a?(Array)
|
31
|
+
local_type = local_type.first
|
32
|
+
end
|
33
|
+
local_type || @schema.get_type(name)
|
28
34
|
end
|
29
35
|
|
30
36
|
# Lookup using `own_types` here because it's ok to override
|
@@ -77,13 +83,13 @@ module GraphQL
|
|
77
83
|
|
78
84
|
def update_type_owner(owner, type)
|
79
85
|
case owner
|
80
|
-
when
|
86
|
+
when Module
|
81
87
|
if owner.kind.union?
|
82
88
|
# It's a union with possible_types
|
83
89
|
# Replace the item by class name
|
84
90
|
owner.assign_type_membership_object_type(type)
|
85
91
|
@possible_types[owner.graphql_name] = owner.possible_types
|
86
|
-
elsif type.kind.interface? && owner.kind.object?
|
92
|
+
elsif type.kind.interface? && (owner.kind.object? || owner.kind.interface?)
|
87
93
|
new_interfaces = []
|
88
94
|
owner.interfaces.each do |int_t|
|
89
95
|
if int_t.is_a?(String) && int_t == type.graphql_name
|
@@ -98,12 +104,11 @@ module GraphQL
|
|
98
104
|
owner.implements(*new_interfaces)
|
99
105
|
new_interfaces.each do |int|
|
100
106
|
pt = @possible_types[int.graphql_name] ||= []
|
101
|
-
if !pt.include?(owner)
|
107
|
+
if !pt.include?(owner) && owner.is_a?(Class)
|
102
108
|
pt << owner
|
103
109
|
end
|
104
110
|
end
|
105
111
|
end
|
106
|
-
|
107
112
|
when nil
|
108
113
|
# It's a root type
|
109
114
|
@types[type.graphql_name] = type
|
@@ -148,42 +153,42 @@ module GraphQL
|
|
148
153
|
um << owner
|
149
154
|
end
|
150
155
|
|
151
|
-
if (prev_type = get_local_type(type.graphql_name))
|
152
|
-
|
153
|
-
raise DuplicateTypeNamesError.new(
|
154
|
-
type_name: type.graphql_name,
|
155
|
-
first_definition: prev_type,
|
156
|
-
second_definition: type,
|
157
|
-
path: path,
|
158
|
-
)
|
159
|
-
else
|
160
|
-
# This type was already added
|
161
|
-
end
|
156
|
+
if (prev_type = get_local_type(type.graphql_name)) && prev_type == type
|
157
|
+
# No need to re-visit
|
162
158
|
elsif type.is_a?(Class) && type < GraphQL::Schema::Directive
|
163
159
|
@directives << type
|
164
|
-
type.
|
160
|
+
type.all_argument_definitions.each do |arg|
|
165
161
|
arg_type = arg.type.unwrap
|
166
162
|
references_to(arg_type, from: arg)
|
167
|
-
add_type(arg_type, owner: arg, late_types: late_types, path: path + [
|
163
|
+
add_type(arg_type, owner: arg, late_types: late_types, path: path + [arg.graphql_name])
|
168
164
|
if arg.default_value?
|
169
165
|
@arguments_with_default_values << arg
|
170
166
|
end
|
171
167
|
end
|
172
168
|
else
|
173
|
-
@types[type.graphql_name]
|
169
|
+
prev_type = @types[type.graphql_name]
|
170
|
+
if prev_type.nil?
|
171
|
+
@types[type.graphql_name] = type
|
172
|
+
elsif prev_type.is_a?(Array)
|
173
|
+
prev_type << type
|
174
|
+
else
|
175
|
+
@types[type.graphql_name] = [prev_type, type]
|
176
|
+
end
|
177
|
+
|
174
178
|
add_directives_from(type)
|
175
179
|
if type.kind.fields?
|
176
|
-
type.
|
180
|
+
type.all_field_definitions.each do |field|
|
181
|
+
name = field.graphql_name
|
177
182
|
field_type = field.type.unwrap
|
178
183
|
references_to(field_type, from: field)
|
179
184
|
field_path = path + [name]
|
180
185
|
add_type(field_type, owner: field, late_types: late_types, path: field_path)
|
181
186
|
add_directives_from(field)
|
182
|
-
field.
|
187
|
+
field.all_argument_definitions.each do |arg|
|
183
188
|
add_directives_from(arg)
|
184
189
|
arg_type = arg.type.unwrap
|
185
190
|
references_to(arg_type, from: arg)
|
186
|
-
add_type(arg_type, owner: arg, late_types: late_types, path: field_path + [
|
191
|
+
add_type(arg_type, owner: arg, late_types: late_types, path: field_path + [arg.graphql_name])
|
187
192
|
if arg.default_value?
|
188
193
|
@arguments_with_default_values << arg
|
189
194
|
end
|
@@ -191,19 +196,19 @@ module GraphQL
|
|
191
196
|
end
|
192
197
|
end
|
193
198
|
if type.kind.input_object?
|
194
|
-
type.
|
199
|
+
type.all_argument_definitions.each do |arg|
|
195
200
|
add_directives_from(arg)
|
196
201
|
arg_type = arg.type.unwrap
|
197
202
|
references_to(arg_type, from: arg)
|
198
|
-
add_type(arg_type, owner: arg, late_types: late_types, path: path + [
|
203
|
+
add_type(arg_type, owner: arg, late_types: late_types, path: path + [arg.graphql_name])
|
199
204
|
if arg.default_value?
|
200
205
|
@arguments_with_default_values << arg
|
201
206
|
end
|
202
207
|
end
|
203
208
|
end
|
204
209
|
if type.kind.union?
|
205
|
-
@possible_types[type.graphql_name] = type.
|
206
|
-
type.
|
210
|
+
@possible_types[type.graphql_name] = type.all_possible_types
|
211
|
+
type.all_possible_types.each do |t|
|
207
212
|
add_type(t, owner: type, late_types: late_types, path: path + ["possible_types"])
|
208
213
|
end
|
209
214
|
end
|
@@ -213,13 +218,17 @@ module GraphQL
|
|
213
218
|
end
|
214
219
|
end
|
215
220
|
if type.kind.object?
|
216
|
-
@possible_types[type.graphql_name]
|
221
|
+
possible_types_for_this_name = @possible_types[type.graphql_name] ||= []
|
222
|
+
possible_types_for_this_name << type
|
223
|
+
end
|
224
|
+
|
225
|
+
if type.kind.object? || type.kind.interface?
|
217
226
|
type.interface_type_memberships.each do |interface_type_membership|
|
218
227
|
case interface_type_membership
|
219
228
|
when Schema::TypeMembership
|
220
229
|
interface_type = interface_type_membership.abstract_type
|
221
230
|
# We can get these now; we'll have to get late-bound types later
|
222
|
-
if interface_type.is_a?(Module)
|
231
|
+
if interface_type.is_a?(Module) && type.is_a?(Class)
|
223
232
|
implementers = @possible_types[interface_type.graphql_name] ||= []
|
224
233
|
implementers << type
|
225
234
|
end
|
@@ -2,10 +2,6 @@
|
|
2
2
|
module GraphQL
|
3
3
|
class Schema
|
4
4
|
class Argument
|
5
|
-
if !String.method_defined?(:-@)
|
6
|
-
using GraphQL::StringDedupBackport
|
7
|
-
end
|
8
|
-
|
9
5
|
include GraphQL::Schema::Member::CachedGraphQLDefinition
|
10
6
|
include GraphQL::Schema::Member::AcceptsDefinition
|
11
7
|
include GraphQL::Schema::Member::HasPath
|
@@ -41,7 +37,7 @@ module GraphQL
|
|
41
37
|
# @param arg_name [Symbol]
|
42
38
|
# @param type_expr
|
43
39
|
# @param desc [String]
|
44
|
-
# @param required [Boolean] if true, this argument is non-null; if false, this argument is nullable
|
40
|
+
# @param required [Boolean, :nullable] if true, this argument is non-null; if false, this argument is nullable. If `:nullable`, then the argument must be provided, though it may be `null`.
|
45
41
|
# @param description [String]
|
46
42
|
# @param default_value [Object]
|
47
43
|
# @param as [Symbol] Override the keyword name when passed to a method
|
@@ -52,13 +48,21 @@ module GraphQL
|
|
52
48
|
# @param directives [Hash{Class => Hash}]
|
53
49
|
# @param deprecation_reason [String]
|
54
50
|
# @param validates [Hash, nil] Options for building validators, if any should be applied
|
55
|
-
|
51
|
+
# @param replace_null_with_default [Boolean] if `true`, incoming values of `null` will be replaced with the configured `default_value`
|
52
|
+
def initialize(arg_name = nil, type_expr = nil, desc = nil, required: true, type: nil, name: nil, loads: nil, description: nil, ast_node: nil, default_value: NO_DEFAULT, as: nil, from_resolver: false, camelize: true, prepare: nil, method_access: true, owner:, validates: nil, directives: nil, deprecation_reason: nil, replace_null_with_default: false, &definition_block)
|
56
53
|
arg_name ||= name
|
57
54
|
@name = -(camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s)
|
58
55
|
@type_expr = type_expr || type
|
59
56
|
@description = desc || description
|
60
|
-
@null =
|
57
|
+
@null = required != true
|
61
58
|
@default_value = default_value
|
59
|
+
if replace_null_with_default
|
60
|
+
if !default_value?
|
61
|
+
raise ArgumentError, "`replace_null_with_default: true` requires a default value, please provide one with `default_value: ...`"
|
62
|
+
end
|
63
|
+
@replace_null_with_default = true
|
64
|
+
end
|
65
|
+
|
62
66
|
@owner = owner
|
63
67
|
@as = as
|
64
68
|
@loads = loads
|
@@ -76,6 +80,9 @@ module GraphQL
|
|
76
80
|
end
|
77
81
|
|
78
82
|
self.validates(validates)
|
83
|
+
if required == :nullable
|
84
|
+
self.owner.validates(required: { argument: arg_name })
|
85
|
+
end
|
79
86
|
|
80
87
|
if definition_block
|
81
88
|
if definition_block.arity == 1
|
@@ -86,6 +93,10 @@ module GraphQL
|
|
86
93
|
end
|
87
94
|
end
|
88
95
|
|
96
|
+
def inspect
|
97
|
+
"#<#{self.class} #{path}: #{type.to_type_signature}#{description ? " @description=#{description.inspect}" : ""}>"
|
98
|
+
end
|
99
|
+
|
89
100
|
# @return [Object] the value used when the client doesn't provide a value for this argument
|
90
101
|
attr_reader :default_value
|
91
102
|
|
@@ -94,6 +105,10 @@ module GraphQL
|
|
94
105
|
@default_value != NO_DEFAULT
|
95
106
|
end
|
96
107
|
|
108
|
+
def replace_null_with_default?
|
109
|
+
@replace_null_with_default
|
110
|
+
end
|
111
|
+
|
97
112
|
attr_writer :description
|
98
113
|
|
99
114
|
# @return [String] Documentation for this argument
|
@@ -147,20 +162,15 @@ module GraphQL
|
|
147
162
|
end
|
148
163
|
end
|
149
164
|
elsif as_type.kind.input_object?
|
150
|
-
as_type.
|
151
|
-
input_obj_arg = input_obj_arg.type_class
|
152
|
-
# TODO: this skips input objects whose values were alread replaced with application objects.
|
153
|
-
# See: https://github.com/rmosolgo/graphql-ruby/issues/2633
|
154
|
-
if value.is_a?(InputObject) && value.key?(input_obj_arg.keyword) && !input_obj_arg.authorized?(obj, value[input_obj_arg.keyword], ctx)
|
155
|
-
return false
|
156
|
-
end
|
157
|
-
end
|
165
|
+
return as_type.authorized?(obj, value, ctx)
|
158
166
|
end
|
159
167
|
# None of the early-return conditions were activated,
|
160
168
|
# so this is authorized.
|
161
169
|
true
|
162
170
|
end
|
163
171
|
|
172
|
+
prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
|
173
|
+
|
164
174
|
def to_graphql
|
165
175
|
argument = GraphQL::Argument.new
|
166
176
|
argument.name = @name
|
@@ -255,6 +265,11 @@ module GraphQL
|
|
255
265
|
return
|
256
266
|
end
|
257
267
|
|
268
|
+
if value.nil? && replace_null_with_default?
|
269
|
+
value = default_value
|
270
|
+
default_used = true
|
271
|
+
end
|
272
|
+
|
258
273
|
loaded_value = nil
|
259
274
|
coerced_value = context.schema.error_handler.with_error_handling(context) do
|
260
275
|
type.coerce_input(value, context)
|
@@ -3,12 +3,7 @@ require "graphql/schema/build_from_definition/resolve_map"
|
|
3
3
|
|
4
4
|
module GraphQL
|
5
5
|
class Schema
|
6
|
-
# TODO Populate `.directive(...)` from here
|
7
6
|
module BuildFromDefinition
|
8
|
-
if !String.method_defined?(:-@)
|
9
|
-
using GraphQL::StringDedupBackport
|
10
|
-
end
|
11
|
-
|
12
7
|
class << self
|
13
8
|
# @see {Schema.from_definition}
|
14
9
|
def from_definition(definition_string, parser: GraphQL.default_parser, **kwargs)
|
@@ -382,6 +377,7 @@ module GraphQL
|
|
382
377
|
Class.new(GraphQL::Schema::Directive) do
|
383
378
|
graphql_name(directive_definition.name)
|
384
379
|
description(directive_definition.description)
|
380
|
+
repeatable(directive_definition.repeatable)
|
385
381
|
locations(*directive_definition.locations.map { |location| location.name.to_sym })
|
386
382
|
ast_node(directive_definition)
|
387
383
|
builder.build_arguments(self, directive_definition.arguments, type_resolver)
|
@@ -394,6 +390,11 @@ module GraphQL
|
|
394
390
|
include GraphQL::Schema::Interface
|
395
391
|
graphql_name(interface_type_definition.name)
|
396
392
|
description(interface_type_definition.description)
|
393
|
+
interface_type_definition.interfaces.each do |interface_name|
|
394
|
+
"Implements: #{interface_type_definition} -> #{interface_name}"
|
395
|
+
interface_defn = type_resolver.call(interface_name)
|
396
|
+
implements(interface_defn)
|
397
|
+
end
|
397
398
|
ast_node(interface_type_definition)
|
398
399
|
builder.build_directives(self, interface_type_definition, type_resolver)
|
399
400
|
|
@@ -35,7 +35,7 @@ module GraphQL
|
|
35
35
|
GraphQL::Schema::Directive::INPUT_FIELD_DEFINITION,
|
36
36
|
)
|
37
37
|
|
38
|
-
argument :by, [String], "Flags to check for this schema member"
|
38
|
+
argument :by, [String], "Flags to check for this schema member"
|
39
39
|
|
40
40
|
module VisibleByFlag
|
41
41
|
def self.included(schema_class)
|
@@ -44,7 +44,7 @@ module GraphQL
|
|
44
44
|
|
45
45
|
def visible?(context)
|
46
46
|
if dir = self.directives.find { |d| d.is_a?(Flagged) }
|
47
|
-
relevant_flags = (f = context[:flags]) && dir.arguments[:by] & f
|
47
|
+
relevant_flags = (f = context[:flags]) && dir.arguments[:by] & f # rubocop:disable Development/ContextIsPassedCop -- definition-related
|
48
48
|
relevant_flags && relevant_flags.any? && super
|
49
49
|
else
|
50
50
|
super
|
@@ -8,6 +8,8 @@ module GraphQL
|
|
8
8
|
# - {.resolve}: Wraps field resolution (so it should call `yield` to continue)
|
9
9
|
class Directive < GraphQL::Schema::Member
|
10
10
|
extend GraphQL::Schema::Member::HasArguments
|
11
|
+
extend GraphQL::Schema::Member::AcceptsDefinition
|
12
|
+
|
11
13
|
class << self
|
12
14
|
# Directives aren't types, they don't have kinds.
|
13
15
|
undef_method :kind
|
@@ -20,7 +22,7 @@ module GraphQL
|
|
20
22
|
# but downcase the first letter.
|
21
23
|
def default_graphql_name
|
22
24
|
@default_graphql_name ||= begin
|
23
|
-
camelized_name = super
|
25
|
+
camelized_name = super.dup
|
24
26
|
camelized_name[0] = camelized_name[0].downcase
|
25
27
|
camelized_name
|
26
28
|
end
|
@@ -53,6 +55,8 @@ module GraphQL
|
|
53
55
|
default_directive
|
54
56
|
end
|
55
57
|
|
58
|
+
prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
|
59
|
+
|
56
60
|
def to_graphql
|
57
61
|
defn = GraphQL::Directive.new
|
58
62
|
defn.name = self.graphql_name
|
@@ -61,9 +65,9 @@ module GraphQL
|
|
61
65
|
defn.default_directive = self.default_directive
|
62
66
|
defn.ast_node = ast_node
|
63
67
|
defn.metadata[:type_class] = self
|
64
|
-
|
65
|
-
arg_graphql = arg_defn.to_graphql
|
66
|
-
defn.arguments[arg_graphql.name] = arg_graphql
|
68
|
+
all_argument_definitions.each do |arg_defn|
|
69
|
+
arg_graphql = arg_defn.to_graphql(silence_deprecation_warning: true)
|
70
|
+
defn.arguments[arg_graphql.name] = arg_graphql # rubocop:disable Development/ContextIsPassedCop -- legacy-related
|
67
71
|
end
|
68
72
|
# Make a reference to a classic-style Arguments class
|
69
73
|
defn.arguments_class = GraphQL::Query::Arguments.construct_arguments_class(defn)
|
@@ -86,6 +90,11 @@ module GraphQL
|
|
86
90
|
yield
|
87
91
|
end
|
88
92
|
|
93
|
+
# Continuing is passed as a block, yield to continue.
|
94
|
+
def resolve_each(object, arguments, context)
|
95
|
+
yield
|
96
|
+
end
|
97
|
+
|
89
98
|
def on_field?
|
90
99
|
locations.include?(FIELD)
|
91
100
|
end
|
@@ -97,6 +106,14 @@ module GraphQL
|
|
97
106
|
def on_operation?
|
98
107
|
locations.include?(QUERY) && locations.include?(MUTATION) && locations.include?(SUBSCRIPTION)
|
99
108
|
end
|
109
|
+
|
110
|
+
def repeatable?
|
111
|
+
!!@repeatable
|
112
|
+
end
|
113
|
+
|
114
|
+
def repeatable(new_value)
|
115
|
+
@repeatable = new_value
|
116
|
+
end
|
100
117
|
end
|
101
118
|
|
102
119
|
# @return [GraphQL::Schema::Field, GraphQL::Schema::Argument, Class, Module]
|
@@ -139,6 +156,7 @@ module GraphQL
|
|
139
156
|
ENUM_VALUE = :ENUM_VALUE,
|
140
157
|
INPUT_OBJECT = :INPUT_OBJECT,
|
141
158
|
INPUT_FIELD_DEFINITION = :INPUT_FIELD_DEFINITION,
|
159
|
+
VARIABLE_DEFINITION = :VARIABLE_DEFINITION,
|
142
160
|
]
|
143
161
|
|
144
162
|
DEFAULT_DEPRECATION_REASON = 'No longer supported'
|
@@ -161,6 +179,7 @@ module GraphQL
|
|
161
179
|
ENUM_VALUE: 'Location adjacent to an enum value definition.',
|
162
180
|
INPUT_OBJECT: 'Location adjacent to an input object type definition.',
|
163
181
|
INPUT_FIELD_DEFINITION: 'Location adjacent to an input object field definition.',
|
182
|
+
VARIABLE_DEFINITION: 'Location adjacent to a variable definition.',
|
164
183
|
}
|
165
184
|
|
166
185
|
private
|