graphql 1.9.17 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/generators/graphql/templates/schema.erb +7 -0
- data/lib/graphql/analysis/ast/field_usage.rb +1 -1
- data/lib/graphql/analysis/ast/visitor.rb +3 -3
- data/lib/graphql/analysis/ast.rb +12 -11
- data/lib/graphql/argument.rb +7 -35
- data/lib/graphql/backtrace/table.rb +10 -2
- data/lib/graphql/base_type.rb +4 -0
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +5 -9
- data/lib/graphql/define/assign_enum_value.rb +1 -1
- data/lib/graphql/define/assign_object_field.rb +3 -3
- data/lib/graphql/define/defined_object_proxy.rb +8 -2
- data/lib/graphql/define/instance_definable.rb +10 -106
- data/lib/graphql/directive/deprecated_directive.rb +1 -12
- data/lib/graphql/directive.rb +4 -1
- data/lib/graphql/enum_type.rb +5 -71
- data/lib/graphql/execution/directive_checks.rb +2 -2
- data/lib/graphql/execution/errors.rb +2 -3
- data/lib/graphql/execution/execute.rb +1 -1
- data/lib/graphql/execution/interpreter/runtime.rb +106 -55
- data/lib/graphql/execution/interpreter.rb +5 -11
- data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
- data/lib/graphql/execution/lookahead.rb +5 -5
- data/lib/graphql/execution/multiplex.rb +13 -3
- data/lib/graphql/field.rb +9 -117
- data/lib/graphql/filter.rb +1 -1
- data/lib/graphql/function.rb +1 -30
- data/lib/graphql/input_object_type.rb +2 -24
- data/lib/graphql/interface_type.rb +2 -23
- data/lib/graphql/introspection/base_object.rb +2 -5
- data/lib/graphql/introspection/directive_type.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +7 -7
- data/lib/graphql/introspection/input_value_type.rb +27 -9
- data/lib/graphql/introspection/schema_type.rb +1 -6
- data/lib/graphql/introspection/type_type.rb +5 -5
- data/lib/graphql/language/definition_slice.rb +21 -10
- data/lib/graphql/language/document_from_schema_definition.rb +50 -44
- data/lib/graphql/language/nodes.rb +3 -3
- data/lib/graphql/language/parser.rb +644 -646
- data/lib/graphql/language/parser.y +6 -4
- data/lib/graphql/language.rb +1 -1
- data/lib/graphql/non_null_type.rb +0 -10
- data/lib/graphql/object_type.rb +1 -21
- data/lib/graphql/pagination/active_record_relation_connection.rb +35 -0
- data/lib/graphql/pagination/array_connection.rb +77 -0
- data/lib/graphql/pagination/connection.rb +171 -0
- data/lib/graphql/pagination/connections.rb +108 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
- data/lib/graphql/pagination/relation_connection.rb +151 -0
- data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
- data/lib/graphql/pagination.rb +6 -0
- data/lib/graphql/query/arguments.rb +2 -1
- data/lib/graphql/query/context.rb +2 -5
- data/lib/graphql/query/literal_input.rb +30 -10
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query/variables.rb +7 -3
- data/lib/graphql/query.rb +9 -5
- data/lib/graphql/relay/base_connection.rb +4 -0
- data/lib/graphql/relay/connection_type.rb +2 -1
- data/lib/graphql/relay/edge_type.rb +1 -0
- data/lib/graphql/relay/edges_instrumentation.rb +1 -1
- data/lib/graphql/relay/mutation.rb +1 -86
- data/lib/graphql/relay/node.rb +2 -2
- data/lib/graphql/scalar_type.rb +1 -58
- data/lib/graphql/schema/argument.rb +51 -6
- data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
- data/lib/graphql/schema/build_from_definition/resolve_map.rb +10 -4
- data/lib/graphql/schema/build_from_definition.rb +167 -178
- data/lib/graphql/schema/built_in_types.rb +5 -5
- data/lib/graphql/schema/directive/deprecated.rb +18 -0
- data/lib/graphql/schema/directive.rb +28 -2
- data/lib/graphql/schema/enum.rb +40 -3
- data/lib/graphql/schema/enum_value.rb +5 -1
- data/lib/graphql/schema/field/connection_extension.rb +11 -1
- data/lib/graphql/schema/field.rb +59 -31
- data/lib/graphql/schema/find_inherited_value.rb +13 -0
- data/lib/graphql/schema/finder.rb +13 -11
- data/lib/graphql/schema/input_object.rb +107 -2
- data/lib/graphql/schema/interface.rb +10 -7
- data/lib/graphql/schema/introspection_system.rb +108 -37
- data/lib/graphql/schema/late_bound_type.rb +1 -0
- data/lib/graphql/schema/list.rb +41 -0
- data/lib/graphql/schema/loader.rb +16 -4
- data/lib/graphql/schema/member/base_dsl_methods.rb +21 -11
- data/lib/graphql/schema/member/build_type.rb +5 -1
- data/lib/graphql/schema/member/cached_graphql_definition.rb +5 -0
- data/lib/graphql/schema/member/has_arguments.rb +2 -2
- data/lib/graphql/schema/member/has_ast_node.rb +17 -0
- data/lib/graphql/schema/member/has_fields.rb +4 -4
- data/lib/graphql/schema/member/validates_input.rb +33 -0
- data/lib/graphql/schema/member.rb +5 -0
- data/lib/graphql/schema/mutation.rb +1 -1
- data/lib/graphql/schema/non_null.rb +25 -0
- data/lib/graphql/schema/object.rb +15 -5
- data/lib/graphql/schema/printer.rb +1 -2
- data/lib/graphql/schema/relay_classic_mutation.rb +1 -1
- data/lib/graphql/schema/resolver.rb +3 -15
- data/lib/graphql/schema/scalar.rb +19 -3
- data/lib/graphql/schema/subscription.rb +5 -5
- data/lib/graphql/schema/traversal.rb +1 -1
- data/lib/graphql/schema/type_expression.rb +21 -13
- data/lib/graphql/schema/type_membership.rb +2 -2
- data/lib/graphql/schema/union.rb +2 -3
- data/lib/graphql/schema/validation.rb +2 -2
- data/lib/graphql/schema/warden.rb +45 -20
- data/lib/graphql/schema.rb +764 -151
- data/lib/graphql/static_validation/base_visitor.rb +10 -6
- 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_are_defined_on_type.rb +4 -4
- 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/fragment_spreads_are_possible.rb +3 -3
- 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/static_validation/type_stack.rb +2 -2
- data/lib/graphql/static_validation/validator.rb +1 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +3 -3
- data/lib/graphql/subscriptions/event.rb +7 -4
- data/lib/graphql/subscriptions/instrumentation.rb +10 -5
- data/lib/graphql/subscriptions/subscription_root.rb +0 -1
- data/lib/graphql/subscriptions.rb +34 -9
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +14 -10
- data/lib/graphql/tracing/appsignal_tracing.rb +8 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +8 -0
- data/lib/graphql/tracing/new_relic_tracing.rb +8 -0
- data/lib/graphql/tracing/platform_tracing.rb +26 -6
- data/lib/graphql/tracing/prometheus_tracing.rb +8 -0
- data/lib/graphql/tracing/scout_tracing.rb +8 -0
- data/lib/graphql/tracing/skylight_tracing.rb +8 -0
- data/lib/graphql/tracing.rb +7 -3
- data/lib/graphql/types/int.rb +1 -1
- data/lib/graphql/types/relay/base_connection.rb +3 -1
- data/lib/graphql/union_type.rb +13 -28
- data/lib/graphql/unresolved_type_error.rb +2 -2
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +2 -1
- metadata +15 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5410e491e639ee266d3c13a8f3073be2d8270289548f6c63e10a056fe5ff8a43
|
|
4
|
+
data.tar.gz: 9b6a6a7dd62e3946b49b0e46c8dbf7745feeb4b48cb931b9d9d2deb9221bb43a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 78f06f66e32517103a861c2adeeeac0f090dbb111d4827a22f3f7a398b8825b10fc1d89bfcc96be3543e8c043351a7023ef1542284bc5ce60518ed5eeb6e6c70
|
|
7
|
+
data.tar.gz: 53264646f1a059b97494503b350de5908d2ca70392c749426d6863275ac4b99f4629dbf18ae21fc21f1bd85fbb02ad4f7f17b7a8ce54a64e0aa89ee6bbee253b
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
class <%= schema_name %> < GraphQL::Schema
|
|
2
|
+
query(Types::QueryType)
|
|
3
|
+
|
|
4
|
+
# Opt in to the new runtime (default in future graphql-ruby versions)
|
|
5
|
+
use GraphQL::Execution::Interpreter
|
|
6
|
+
|
|
7
|
+
# Add built-in connections for pagination
|
|
8
|
+
use GraphQL::Pagination::Connections
|
|
2
9
|
<% if options[:relay] %>
|
|
3
10
|
# Relay Object Identification:
|
|
4
11
|
|
|
@@ -11,7 +11,7 @@ module GraphQL
|
|
|
11
11
|
|
|
12
12
|
def on_leave_field(node, parent, visitor)
|
|
13
13
|
field_defn = visitor.field_definition
|
|
14
|
-
field = "#{visitor.parent_type_definition.
|
|
14
|
+
field = "#{visitor.parent_type_definition.graphql_name}.#{field_defn.graphql_name}"
|
|
15
15
|
@used_fields << field
|
|
16
16
|
@used_deprecated_fields << field if field_defn.deprecation_reason
|
|
17
17
|
end
|
|
@@ -134,7 +134,7 @@ module GraphQL
|
|
|
134
134
|
argument_defn = if (arg = @argument_definitions.last)
|
|
135
135
|
arg_type = arg.type.unwrap
|
|
136
136
|
if arg_type.kind.input_object?
|
|
137
|
-
arg_type.
|
|
137
|
+
arg_type.arguments[node.name]
|
|
138
138
|
else
|
|
139
139
|
nil
|
|
140
140
|
end
|
|
@@ -214,7 +214,7 @@ module GraphQL
|
|
|
214
214
|
fragment_def = query.fragments[fragment_spread.name]
|
|
215
215
|
|
|
216
216
|
object_type = if fragment_def.type
|
|
217
|
-
query.
|
|
217
|
+
@query.warden.get_type(fragment_def.type.name)
|
|
218
218
|
else
|
|
219
219
|
object_types.last
|
|
220
220
|
end
|
|
@@ -245,7 +245,7 @@ module GraphQL
|
|
|
245
245
|
|
|
246
246
|
def on_fragment_with_type(node)
|
|
247
247
|
object_type = if node.type
|
|
248
|
-
@
|
|
248
|
+
@query.warden.get_type(node.type.name)
|
|
249
249
|
else
|
|
250
250
|
@object_types.last
|
|
251
251
|
end
|
data/lib/graphql/analysis/ast.rb
CHANGED
|
@@ -12,9 +12,8 @@ module GraphQL
|
|
|
12
12
|
module AST
|
|
13
13
|
module_function
|
|
14
14
|
|
|
15
|
-
def use(
|
|
16
|
-
|
|
17
|
-
schema.analysis_engine = GraphQL::Analysis::AST
|
|
15
|
+
def use(schema_class)
|
|
16
|
+
schema_class.analysis_engine = GraphQL::Analysis::AST
|
|
18
17
|
end
|
|
19
18
|
|
|
20
19
|
# Analyze a multiplex, and all queries within.
|
|
@@ -60,16 +59,18 @@ module GraphQL
|
|
|
60
59
|
.select { |analyzer| analyzer.analyze? }
|
|
61
60
|
|
|
62
61
|
analyzers_to_run = query_analyzers + multiplex_analyzers
|
|
63
|
-
|
|
62
|
+
if analyzers_to_run.any?
|
|
63
|
+
visitor = GraphQL::Analysis::AST::Visitor.new(
|
|
64
|
+
query: query,
|
|
65
|
+
analyzers: analyzers_to_run
|
|
66
|
+
)
|
|
64
67
|
|
|
65
|
-
|
|
66
|
-
query: query,
|
|
67
|
-
analyzers: analyzers_to_run
|
|
68
|
-
)
|
|
68
|
+
visitor.visit
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
query_analyzers.map(&:result)
|
|
71
|
+
else
|
|
72
|
+
[]
|
|
73
|
+
end
|
|
73
74
|
end
|
|
74
75
|
end
|
|
75
76
|
|
data/lib/graphql/argument.rb
CHANGED
|
@@ -1,38 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module GraphQL
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
# {#name} must be a String.
|
|
6
|
-
#
|
|
7
|
-
# @example defining an argument for a field
|
|
8
|
-
# GraphQL::Field.define do
|
|
9
|
-
# # ...
|
|
10
|
-
# argument :favoriteFood, types.String, "Favorite thing to eat", default_value: "pizza"
|
|
11
|
-
# end
|
|
12
|
-
#
|
|
13
|
-
# @example defining an argument for an {InputObjectType}
|
|
14
|
-
# GraphQL::InputObjectType.define do
|
|
15
|
-
# argument :newName, !types.String
|
|
16
|
-
# end
|
|
17
|
-
#
|
|
18
|
-
# @example defining an argument with a `prepare` function
|
|
19
|
-
# GraphQL::Field.define do
|
|
20
|
-
# argument :userId, types.ID, prepare: ->(userId) do
|
|
21
|
-
# User.find_by(id: userId)
|
|
22
|
-
# end
|
|
23
|
-
# end
|
|
24
|
-
#
|
|
25
|
-
# @example returning an {ExecutionError} from a `prepare` function
|
|
26
|
-
# GraphQL::Field.define do
|
|
27
|
-
# argument :date do
|
|
28
|
-
# type !types.String
|
|
29
|
-
# prepare ->(date) do
|
|
30
|
-
# return GraphQL::ExecutionError.new("Invalid date format") unless DateValidator.valid?(date)
|
|
31
|
-
# Time.zone.parse(date)
|
|
32
|
-
# end
|
|
33
|
-
# end
|
|
34
|
-
# end
|
|
35
|
-
|
|
3
|
+
# @api deprecated
|
|
36
4
|
class Argument
|
|
37
5
|
include GraphQL::Define::InstanceDefinable
|
|
38
6
|
accepts_definitions :name, :type, :description, :default_value, :as, :prepare, :method_access
|
|
@@ -113,6 +81,10 @@ module GraphQL
|
|
|
113
81
|
@prepare_proc = BackwardsCompatibility.wrap_arity(prepare_proc, from: 1, to: 2, name: "Argument#prepare(value, ctx)")
|
|
114
82
|
end
|
|
115
83
|
|
|
84
|
+
def type_class
|
|
85
|
+
metadata[:type_class]
|
|
86
|
+
end
|
|
87
|
+
|
|
116
88
|
NO_DEFAULT_VALUE = Object.new
|
|
117
89
|
# @api private
|
|
118
90
|
def self.from_dsl(name, type_or_argument = nil, description = nil, default_value: NO_DEFAULT_VALUE, as: nil, prepare: DefaultPrepare, **kwargs, &block)
|
|
@@ -134,9 +106,9 @@ module GraphQL
|
|
|
134
106
|
end
|
|
135
107
|
|
|
136
108
|
if type_or_argument.is_a?(GraphQL::Argument)
|
|
137
|
-
type_or_argument.redefine(kwargs, &block)
|
|
109
|
+
type_or_argument.redefine(**kwargs, &block)
|
|
138
110
|
else
|
|
139
|
-
GraphQL::Argument.define(kwargs, &block)
|
|
111
|
+
GraphQL::Argument.define(**kwargs, &block)
|
|
140
112
|
end
|
|
141
113
|
end
|
|
142
114
|
|
|
@@ -84,10 +84,14 @@ module GraphQL
|
|
|
84
84
|
field_name = "#{ctx.irep_node.owner_type.name}.#{ctx.field.name}"
|
|
85
85
|
position = "#{ctx.ast_node.line}:#{ctx.ast_node.col}"
|
|
86
86
|
field_alias = ctx.ast_node.alias
|
|
87
|
+
object = ctx.object
|
|
88
|
+
if object.is_a?(GraphQL::Schema::Object)
|
|
89
|
+
object = object.object
|
|
90
|
+
end
|
|
87
91
|
rows << [
|
|
88
92
|
"#{position}",
|
|
89
93
|
"#{field_name}#{field_alias ? " as #{field_alias}" : ""}",
|
|
90
|
-
"#{
|
|
94
|
+
"#{object.inspect}",
|
|
91
95
|
ctx.irep_node.arguments.to_h.inspect,
|
|
92
96
|
Backtrace::InspectResult.inspect_result(top && @override_value ? @override_value : ctx.value),
|
|
93
97
|
]
|
|
@@ -104,10 +108,14 @@ module GraphQL
|
|
|
104
108
|
position = "?:?"
|
|
105
109
|
end
|
|
106
110
|
op_name = query.selected_operation_name
|
|
111
|
+
object = query.root_value
|
|
112
|
+
if object.is_a?(GraphQL::Schema::Object)
|
|
113
|
+
object = object.object
|
|
114
|
+
end
|
|
107
115
|
rows << [
|
|
108
116
|
"#{position}",
|
|
109
117
|
"#{op_type}#{op_name ? " #{op_name}" : ""}",
|
|
110
|
-
"#{
|
|
118
|
+
"#{object.inspect}",
|
|
111
119
|
query.variables.to_h.inspect,
|
|
112
120
|
Backtrace::InspectResult.inspect_result(query.context.value),
|
|
113
121
|
]
|
data/lib/graphql/base_type.rb
CHANGED
|
@@ -70,15 +70,11 @@ module GraphQL
|
|
|
70
70
|
")
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
def
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def test_it_parses_blank_queries
|
|
79
|
-
assert_empty_document("")
|
|
80
|
-
assert_empty_document(" ")
|
|
81
|
-
assert_empty_document("\t \t")
|
|
73
|
+
def test_it_rejects_blank_queries
|
|
74
|
+
assert_raises_parse_error("")
|
|
75
|
+
assert_raises_parse_error(" ")
|
|
76
|
+
assert_raises_parse_error("\t \t")
|
|
77
|
+
assert_raises_parse_error(" # comment ")
|
|
82
78
|
end
|
|
83
79
|
|
|
84
80
|
def test_it_restricts_on
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module GraphQL
|
|
3
3
|
module Define
|
|
4
|
-
#
|
|
4
|
+
# @api deprecated
|
|
5
5
|
module AssignEnumValue
|
|
6
6
|
def self.call(enum_type, name, desc = nil, deprecation_reason: nil, value: name, &block)
|
|
7
7
|
enum_value = GraphQL::EnumType::EnumValue.define(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module GraphQL
|
|
3
3
|
module Define
|
|
4
|
-
#
|
|
4
|
+
# @api deprecated
|
|
5
5
|
module AssignObjectField
|
|
6
6
|
def self.call(owner_type, name, type_or_field = nil, desc = nil, function: nil, field: nil, relay_mutation_function: nil, **kwargs, &block)
|
|
7
7
|
name_s = name.to_s
|
|
@@ -28,9 +28,9 @@ module GraphQL
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
obj_field = if base_field
|
|
31
|
-
base_field.redefine(kwargs, &block)
|
|
31
|
+
base_field.redefine(**kwargs, &block)
|
|
32
32
|
else
|
|
33
|
-
GraphQL::Field.define(kwargs, &block)
|
|
33
|
+
GraphQL::Field.define(**kwargs, &block)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
|
|
@@ -32,10 +32,16 @@ module GraphQL
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
# Lookup a function from the dictionary and call it if it's found.
|
|
35
|
-
def method_missing(name, *args, &block)
|
|
35
|
+
def method_missing(name, *args, **kwargs, &block)
|
|
36
36
|
definition = @dictionary[name]
|
|
37
37
|
if definition
|
|
38
|
-
|
|
38
|
+
# Avoid passing `kwargs` when it's not used.
|
|
39
|
+
# Ruby 2.7 does fine here, but older Rubies receive too many arguments.
|
|
40
|
+
if kwargs.any?
|
|
41
|
+
definition.call(@target, *args, **kwargs, &block)
|
|
42
|
+
else
|
|
43
|
+
definition.call(@target, *args, &block)
|
|
44
|
+
end
|
|
39
45
|
else
|
|
40
46
|
msg = "#{@target.class.name} can't define '#{name}'"
|
|
41
47
|
raise NoDefinitionError, msg, caller
|
|
@@ -1,118 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module GraphQL
|
|
3
3
|
module Define
|
|
4
|
-
#
|
|
5
|
-
# {GraphQL::BaseType}, {GraphQL::Field} and others.
|
|
6
|
-
#
|
|
7
|
-
# Calling `.accepts_definitions(...)` creates:
|
|
8
|
-
#
|
|
9
|
-
# - a keyword to the `.define` method
|
|
10
|
-
# - a helper method in the `.define { ... }` block
|
|
11
|
-
#
|
|
12
|
-
# The `.define { ... }` block will be called lazily. To be sure it has been
|
|
13
|
-
# called, use the private method `#ensure_defined`. That will call the
|
|
14
|
-
# definition block if it hasn't been called already.
|
|
15
|
-
#
|
|
16
|
-
# The goals are:
|
|
17
|
-
#
|
|
18
|
-
# - Minimal overhead in consuming classes
|
|
19
|
-
# - Independence between consuming classes
|
|
20
|
-
# - Extendable by third-party libraries without monkey-patching or other nastiness
|
|
21
|
-
#
|
|
22
|
-
# @example Make a class definable
|
|
23
|
-
# class Car
|
|
24
|
-
# include GraphQL::Define::InstanceDefinable
|
|
25
|
-
# attr_accessor :make, :model, :doors
|
|
26
|
-
# accepts_definitions(
|
|
27
|
-
# # These attrs will be defined with plain setters, `{attr}=`
|
|
28
|
-
# :make, :model,
|
|
29
|
-
# # This attr has a custom definition which applies the config to the target
|
|
30
|
-
# doors: ->(car, doors_count) { doors_count.times { car.doors << Door.new } }
|
|
31
|
-
# )
|
|
32
|
-
# ensure_defined(:make, :model, :doors)
|
|
33
|
-
#
|
|
34
|
-
# def initialize
|
|
35
|
-
# @doors = []
|
|
36
|
-
# end
|
|
37
|
-
# end
|
|
38
|
-
#
|
|
39
|
-
# class Door; end;
|
|
40
|
-
#
|
|
41
|
-
# # Create an instance with `.define`:
|
|
42
|
-
# subaru_baja = Car.define do
|
|
43
|
-
# make "Subaru"
|
|
44
|
-
# model "Baja"
|
|
45
|
-
# doors 4
|
|
46
|
-
# end
|
|
47
|
-
#
|
|
48
|
-
# # The custom proc was applied:
|
|
49
|
-
# subaru_baja.doors #=> [<Door>, <Door>, <Door>, <Door>]
|
|
50
|
-
#
|
|
51
|
-
# @example Extending the definition of a class
|
|
52
|
-
# # Add some definitions:
|
|
53
|
-
# Car.accepts_definitions(all_wheel_drive: GraphQL::Define.assign_metadata_key(:all_wheel_drive))
|
|
54
|
-
#
|
|
55
|
-
# # Use it in a definition
|
|
56
|
-
# subaru_baja = Car.define do
|
|
57
|
-
# # ...
|
|
58
|
-
# all_wheel_drive true
|
|
59
|
-
# end
|
|
60
|
-
#
|
|
61
|
-
# # Access it from metadata
|
|
62
|
-
# subaru_baja.metadata[:all_wheel_drive] # => true
|
|
63
|
-
#
|
|
64
|
-
# @example Extending the definition of a class via a plugin
|
|
65
|
-
# # A plugin is any object that responds to `.use(definition)`
|
|
66
|
-
# module SubaruCar
|
|
67
|
-
# extend self
|
|
68
|
-
#
|
|
69
|
-
# def use(defn)
|
|
70
|
-
# # `defn` has the same methods as within `.define { ... }` block
|
|
71
|
-
# defn.make "Subaru"
|
|
72
|
-
# defn.doors 4
|
|
73
|
-
# end
|
|
74
|
-
# end
|
|
75
|
-
#
|
|
76
|
-
# # Use the plugin within a `.define { ... }` block
|
|
77
|
-
# subaru_baja = Car.define do
|
|
78
|
-
# use SubaruCar
|
|
79
|
-
# model 'Baja'
|
|
80
|
-
# end
|
|
81
|
-
#
|
|
82
|
-
# subaru_baja.make # => "Subaru"
|
|
83
|
-
# subaru_baja.doors # => [<Door>, <Door>, <Door>, <Door>]
|
|
84
|
-
#
|
|
85
|
-
# @example Making a copy with an extended definition
|
|
86
|
-
# # Create an instance with `.define`:
|
|
87
|
-
# subaru_baja = Car.define do
|
|
88
|
-
# make "Subaru"
|
|
89
|
-
# model "Baja"
|
|
90
|
-
# doors 4
|
|
91
|
-
# end
|
|
92
|
-
#
|
|
93
|
-
# # Then extend it with `#redefine`
|
|
94
|
-
# two_door_baja = subaru_baja.redefine do
|
|
95
|
-
# doors 2
|
|
96
|
-
# end
|
|
4
|
+
# @api deprecated
|
|
97
5
|
module InstanceDefinable
|
|
98
6
|
def self.included(base)
|
|
99
7
|
base.extend(ClassMethods)
|
|
100
8
|
base.ensure_defined(:metadata)
|
|
101
9
|
end
|
|
102
10
|
|
|
103
|
-
#
|
|
104
|
-
#
|
|
105
|
-
# @return [Hash<Object, Object>] Hash for user-defined storage
|
|
11
|
+
# @api deprecated
|
|
106
12
|
def metadata
|
|
107
13
|
@metadata ||= {}
|
|
108
14
|
end
|
|
109
15
|
|
|
110
|
-
#
|
|
111
|
-
# Keywords or helpers in the block correspond to keys given to `accepts_definitions`.
|
|
112
|
-
#
|
|
113
|
-
# Note that the block is not called right away -- instead, it's deferred until
|
|
114
|
-
# one of the defined fields is needed.
|
|
115
|
-
# @return [void]
|
|
16
|
+
# @api deprecated
|
|
116
17
|
def define(**kwargs, &block)
|
|
117
18
|
# make sure the previous definition_proc was executed:
|
|
118
19
|
ensure_defined
|
|
@@ -121,9 +22,7 @@ module GraphQL
|
|
|
121
22
|
nil
|
|
122
23
|
end
|
|
123
24
|
|
|
124
|
-
#
|
|
125
|
-
# @see {#define} for arguments
|
|
126
|
-
# @return [InstanceDefinable] A new instance, with any extended definitions
|
|
25
|
+
# @api deprecated
|
|
127
26
|
def redefine(**kwargs, &block)
|
|
128
27
|
ensure_defined
|
|
129
28
|
new_inst = self.dup
|
|
@@ -154,7 +53,12 @@ module GraphQL
|
|
|
154
53
|
defn_proxy = DefinedObjectProxy.new(self)
|
|
155
54
|
# Apply definition from `define(...)` kwargs
|
|
156
55
|
defn.define_keywords.each do |keyword, value|
|
|
157
|
-
|
|
56
|
+
# Don't splat string hashes, which blows up on Rubies before 2.7
|
|
57
|
+
if value.is_a?(Hash) && value.each_key.all? { |k| k.is_a?(Symbol) }
|
|
58
|
+
defn_proxy.public_send(keyword, **value)
|
|
59
|
+
else
|
|
60
|
+
defn_proxy.public_send(keyword, value)
|
|
61
|
+
end
|
|
158
62
|
end
|
|
159
63
|
# and/or apply definition from `define { ... }` block
|
|
160
64
|
if defn.define_proc
|
|
@@ -1,13 +1,2 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
GraphQL::Directive::DeprecatedDirective = GraphQL::Directive.
|
|
3
|
-
name "deprecated"
|
|
4
|
-
description "Marks an element of a GraphQL schema as no longer supported."
|
|
5
|
-
locations([GraphQL::Directive::FIELD_DEFINITION, GraphQL::Directive::ENUM_VALUE])
|
|
6
|
-
|
|
7
|
-
reason_description = "Explains why this element was deprecated, usually also including a "\
|
|
8
|
-
"suggestion for how to access supported similar data. Formatted "\
|
|
9
|
-
"in [Markdown](https://daringfireball.net/projects/markdown/)."
|
|
10
|
-
|
|
11
|
-
argument :reason, GraphQL::STRING_TYPE, reason_description, default_value: GraphQL::Directive::DEFAULT_DEPRECATION_REASON
|
|
12
|
-
default_directive true
|
|
13
|
-
end
|
|
2
|
+
GraphQL::Directive::DeprecatedDirective = GraphQL::Schema::Directive::Deprecated.graphql_definition
|
data/lib/graphql/directive.rb
CHANGED
|
@@ -45,7 +45,6 @@ module GraphQL
|
|
|
45
45
|
INPUT_FIELD_DEFINITION = :INPUT_FIELD_DEFINITION,
|
|
46
46
|
]
|
|
47
47
|
|
|
48
|
-
DEFAULT_DEPRECATION_REASON = 'No longer supported'
|
|
49
48
|
LOCATION_DESCRIPTIONS = {
|
|
50
49
|
QUERY: 'Location adjacent to a query operation.',
|
|
51
50
|
MUTATION: 'Location adjacent to a mutation operation.',
|
|
@@ -96,6 +95,10 @@ module GraphQL
|
|
|
96
95
|
def inspect
|
|
97
96
|
"#<GraphQL::Directive #{name}>"
|
|
98
97
|
end
|
|
98
|
+
|
|
99
|
+
def type_class
|
|
100
|
+
metadata[:type_class]
|
|
101
|
+
end
|
|
99
102
|
end
|
|
100
103
|
end
|
|
101
104
|
|
data/lib/graphql/enum_type.rb
CHANGED
|
@@ -1,76 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module GraphQL
|
|
3
|
-
#
|
|
4
|
-
# By convention, enum names are `SCREAMING_CASE_NAMES`,
|
|
5
|
-
# but other identifiers are supported too.
|
|
6
|
-
#
|
|
7
|
-
# You can use as return types _or_ as inputs.
|
|
8
|
-
#
|
|
9
|
-
# By default, enums are passed to `resolve` functions as
|
|
10
|
-
# the strings that identify them, but you can provide a
|
|
11
|
-
# custom Ruby value with the `value:` keyword.
|
|
12
|
-
#
|
|
13
|
-
# @example An enum of programming languages
|
|
14
|
-
# LanguageEnum = GraphQL::EnumType.define do
|
|
15
|
-
# name "Language"
|
|
16
|
-
# description "Programming language for Web projects"
|
|
17
|
-
# value("PYTHON", "A dynamic, function-oriented language")
|
|
18
|
-
# value("RUBY", "A very dynamic language aimed at programmer happiness")
|
|
19
|
-
# value("JAVASCRIPT", "Accidental lingua franca of the web")
|
|
20
|
-
# end
|
|
21
|
-
#
|
|
22
|
-
# @example Using an enum as a return type
|
|
23
|
-
# field :favoriteLanguage, LanguageEnum, "This person's favorite coding language"
|
|
24
|
-
# # ...
|
|
25
|
-
# # In a query:
|
|
26
|
-
# Schema.execute("{ coder(id: 1) { favoriteLanguage } }")
|
|
27
|
-
# # { "data" => { "coder" => { "favoriteLanguage" => "RUBY" } } }
|
|
28
|
-
#
|
|
29
|
-
# @example Defining an enum input
|
|
30
|
-
# field :coders, types[CoderType] do
|
|
31
|
-
# argument :knowing, types[LanguageEnum]
|
|
32
|
-
# resolve ->(obj, args, ctx) {
|
|
33
|
-
# Coder.where(language: args[:knowing])
|
|
34
|
-
# }
|
|
35
|
-
# end
|
|
36
|
-
#
|
|
37
|
-
# @example Using an enum as input
|
|
38
|
-
# {
|
|
39
|
-
# # find coders who know Python and Ruby
|
|
40
|
-
# coders(knowing: [PYTHON, RUBY]) {
|
|
41
|
-
# name
|
|
42
|
-
# hourlyRate
|
|
43
|
-
# }
|
|
44
|
-
# }
|
|
45
|
-
#
|
|
46
|
-
# @example Enum whose values are different in Ruby-land
|
|
47
|
-
# GraphQL::EnumType.define do
|
|
48
|
-
# # ...
|
|
49
|
-
# # use the `value:` keyword:
|
|
50
|
-
# value("RUBY", "Lisp? Smalltalk?", value: :rb)
|
|
51
|
-
# end
|
|
52
|
-
#
|
|
53
|
-
# # Now, resolve functions will receive `:rb` instead of `"RUBY"`
|
|
54
|
-
# field :favoriteLanguage, LanguageEnum
|
|
55
|
-
# resolve ->(obj, args, ctx) {
|
|
56
|
-
# args[:favoriteLanguage] # => :rb
|
|
57
|
-
# }
|
|
58
|
-
#
|
|
59
|
-
# @example Enum whose values are different in ActiveRecord-land
|
|
60
|
-
# class Language < ActiveRecord::Base
|
|
61
|
-
# enum language: {
|
|
62
|
-
# rb: 0
|
|
63
|
-
# }
|
|
64
|
-
# end
|
|
65
|
-
#
|
|
66
|
-
# # Now enum type should be defined as
|
|
67
|
-
# GraphQL::EnumType.define do
|
|
68
|
-
# # ...
|
|
69
|
-
# # use the `value:` keyword:
|
|
70
|
-
# value("RUBY", "Lisp? Smalltalk?", value: 'rb')
|
|
71
|
-
# end
|
|
72
|
-
#
|
|
73
|
-
|
|
3
|
+
# @api deprecated
|
|
74
4
|
class EnumType < GraphQL::BaseType
|
|
75
5
|
accepts_definitions :values, value: GraphQL::Define::AssignEnumValue
|
|
76
6
|
ensure_defined(:values, :validate_non_null_input, :coerce_non_null_input, :coerce_result)
|
|
@@ -151,6 +81,10 @@ module GraphQL
|
|
|
151
81
|
def graphql_name
|
|
152
82
|
name
|
|
153
83
|
end
|
|
84
|
+
|
|
85
|
+
def type_class
|
|
86
|
+
metadata[:type_class]
|
|
87
|
+
end
|
|
154
88
|
end
|
|
155
89
|
|
|
156
90
|
class UnresolvedValueError < GraphQL::Error
|
|
@@ -18,12 +18,12 @@ module GraphQL
|
|
|
18
18
|
case name
|
|
19
19
|
when SKIP
|
|
20
20
|
args = query.arguments_for(directive_ast_node, directive_defn)
|
|
21
|
-
if args[
|
|
21
|
+
if args[:if] == true
|
|
22
22
|
return false
|
|
23
23
|
end
|
|
24
24
|
when INCLUDE
|
|
25
25
|
args = query.arguments_for(directive_ast_node, directive_defn)
|
|
26
|
-
if args[
|
|
26
|
+
if args[:if] == false
|
|
27
27
|
return false
|
|
28
28
|
end
|
|
29
29
|
else
|
|
@@ -18,8 +18,7 @@ module GraphQL
|
|
|
18
18
|
#
|
|
19
19
|
class Errors
|
|
20
20
|
def self.use(schema)
|
|
21
|
-
|
|
22
|
-
schema_class.error_handler = self.new(schema_class)
|
|
21
|
+
schema.error_handler = self.new(schema)
|
|
23
22
|
end
|
|
24
23
|
|
|
25
24
|
def initialize(schema)
|
|
@@ -41,7 +40,7 @@ module GraphQL
|
|
|
41
40
|
def with_error_handling(ctx)
|
|
42
41
|
yield
|
|
43
42
|
rescue StandardError => err
|
|
44
|
-
rescues =
|
|
43
|
+
rescues = ctx.schema.rescues
|
|
45
44
|
_err_class, handler = rescues.find { |err_class, handler| err.is_a?(err_class) }
|
|
46
45
|
if handler
|
|
47
46
|
runtime_info = ctx.namespace(:interpreter) || {}
|
|
@@ -20,7 +20,7 @@ module GraphQL
|
|
|
20
20
|
|
|
21
21
|
def execute(ast_operation, root_type, query)
|
|
22
22
|
result = resolve_root_selection(query)
|
|
23
|
-
lazy_resolve_root_selection(result, {query: query})
|
|
23
|
+
lazy_resolve_root_selection(result, **{query: query})
|
|
24
24
|
GraphQL::Execution::Flatten.call(query.context)
|
|
25
25
|
end
|
|
26
26
|
|